2012-01-01 24 views
5

में निरस्त http कनेक्शन पर एफडी को साफ रूप से बंद करने के लिए कैसे करें मैं नोड के साथ खेल रहा हूं और (फिलहाल) HTTP पर फाइल सिस्टम से कुछ फ़ाइलों को स्ट्रीम करने की कोशिश कर रहा हूं।node.js

मेरे ओएस एक्स शेर मशीन पर अपाचे बेंच (एबी) ऐप छोटी है और समय से कनेक्शन को निरस्त करना प्रतीत होता है। ऐसा लगता है कि मेरे node.js ऐप के साथ एक समस्या पर प्रकाश डाला गया है, जहां कनेक्शन निरस्त हो जाता है, जहां यह फ़ाइल हैंडल को लीक करता है।

मैंने इसे एक साधारण node.js परीक्षण केस में कम कर दिया है। जब मैं इस का शुभारंभ और 'अब' इसके खिलाफ चलाने के लिए, मैं अंत में भी कई फ़ाइल खोलने की वजह से एक EMFILE अपवाद संभालता है:

// app.js 

var count = 0; 
require('http').createServer(function(req,res){ 

    console.log('request ' + ++count); 

    res.writeHead(200); 
    require('fs').createReadStream(
     '/Users/tom/files/8339cdf73594d8f0aab87da123e9e0380723b471' 
    ).pipe(res); 

}).listen('3000'); 


$ node app.js 
request 1 
... 
request 317 
request 318 
request 319 

stream.js:105 
     throw er; // Unhandled stream error in pipe. 
      ^
Error: EMFILE, too many open files '/Users/tom/files/8339cdf73594d8f0aab87da123e9e0380723b471' 

मुझे लगता है क्या हो रहा है HTTP कनेक्शन निरस्त किया गया है, लेकिन है नोड के .pipe() तंत्र को पठनीय धारा से पढ़ने और एफडी को बंद करने के बारे में नहीं पता है, इसलिए मैंने HTTP सर्वर रिक्वेस्ट पर 'क्लोज़' ईवेंट को संभालने और एफडी को नष्ट करने की कोशिश की, लेकिन ऐसा लगता है कि मुझे बुरा लगता है एफडी त्रुटि (EBADF) के बजाय:

// app.js 

var count = 0; 
require('http').createServer(function(req,res){ 

    console.log('request ' + ++count); 

    res.writeHead(200); 
    var file = require('fs').createReadStream(
     '/Users/tom/dev/cloudstore2/files/8339cdf73594d8f0aab87da123e9e0380723b471' 
    ); 

    req.on('close', function(){ 
     console.log('request received close - destroying read FD'); 
     file.destroy(); 
    }); 

    file.pipe(res); 

}).listen('3000'); 

$ node app.js 
... 
request 112 
request 113 
request received close - destroying read FD 
request received close - destroying read FD 
request received close - destroying read FD 
request received close - destroying read FD 
request received close - destroying read FD 
request received close - destroying read FD 
request received close - destroying read FD 

events.js:48 
     throw arguments[1]; // Unhandled 'error' event 
        ^
Error: EBADF, bad file descriptor 

वहाँ एक 'सही' जिस तरह से इन गर्भपात HTTP कनेक्शन संभालने के लिए और बंद मेरी संबद्ध FS स्ट्रीम पढ़ें, या कर रहा हूँ करने के लिए है मैं node.js '.pipe() हैंडलिंग में एक बग देख रहा हूँ?


अद्यतन: मेरी फाइल पाठक पर 'त्रुटि' घटना को पकड़ने, मैं अनुप्रयोग इस प्रक्रिया के दौरान मरने से बच सकते हैं, लेकिन सही तरीका यह है कि है? मुझे लगता है कि मुझे पहली जगह खराब एफडी त्रुटि फेंकने से बचने के लिए कुछ रास्ता याद आ रहा है।

<snip> 
    var file = require('fs').createReadStream(
     '/Users/tom/dev/cloudstore2/files/8339cdf73594d8f0aab87da123e9e0380723b471' 
    ); 

    file.on('error', function(err){ 
     console.log('error handled in file reader: ' + err); 
    }); 

    req.on('close', function(){ 
     console.log('request received close - destroying read FD'); 
     file.destroy(); 
    }); 

    file.pipe(res); 
</snip> 

उत्तर

2

NodeJS प्रलेखन के अनुसार

http.ServerRequest

घटना: 'बंद'

इंगित करता है कि अंतर्निहित कनेक्शन response.end से पहले समाप्त किया गया() बुलाया या फ्लश करने में सक्षम था।

बस 'अंत' की तरह, यह घटना प्रति अनुरोध केवल एक बार होती है, और 'डेटा' ईवेंट बाद में आग लग जाएगी।

नोट: 'बंद' 'अंत' के बाद आग लग सकता है, लेकिन इसके विपरीत नहीं।

मुझे लगता है कि अंत() अपने पाइप जो करता है, तो अंत के सक्रिय होने पर पहले वहाँ एक छोटी सी खिड़की जहां पाइप के बाद यह बंद है अनुरोध एफ एच के लिए लिखने की कोशिश कर किया जा सकता है इसका मतलब है गंतव्य एफ एच मारता है। अंत में() घटना में अपनी file.destroy() कॉल डालने का प्रयास करें।

मैंने अपने विचार का परीक्षण करने की कोशिश की लेकिन मुझे त्रुटि नहीं मिल रही है, इसलिए कृपया मुझे बताएं कि क्या यह आपके लिए काम करता है। मुझे चिंता है कि जब मैं अपने ऐप को अन्य उपयोगकर्ताओं तक खोलता हूं तो मैं इस समस्या में भाग लेगा।

+0

यह सही है, लेकिन जब मैं इस प्रश्न को दर्ज करता था तब उपलब्ध नहीं था। :) मैंने नोड समस्या 2453 (https://github.com/joyent/node/issues/2453) दायर की और 'करीबी' घटना को जोड़ा गया। – dec