Estoy jugando con el nodo y (por el momento) simplemente tratando de transmitir algunos archivos desde el sistema de archivos a través de HTTP.Cómo cerrar limpiamente FD en la conexión HTTP abortada en node.js
La aplicación Apache Bench (ab) en mi máquina OS X Lion tiene errores y parece abortar las conexiones prematuramente. Esto parece haber resaltado un problema con mi aplicación node.js donde filtra manejadores de archivo si la conexión se cancela.
He reducido esto a un caso de prueba node.js simple. Cuando inicio esta y corro 'ab' en contra de ella, al final me consigo una excepción EMFILE debido a demasiados identificadores de archivo abierto:
// 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'
asumo lo que está sucediendo es la conexión HTTP concluye, pero .pipe del nodo() mecanismo no sabe dejar de leer de la secuencia legible y cerrar el FD, así que traté de manejar el evento 'cerrar' en el HTTP ServerRequest y destruir el FD, pero algo parece estar leyendo de él ya que me da un mal error FD (EBADF) en su lugar:
// 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
¿hay una manera 'correcta' para manejar estas conexiones HTTP abortados y cerrar mi F relacionados leen corriente, o aM ¿Veo un error en el manejo de node.js '.pipe()?
Actualización: Al detectar el evento 'error' en mi lector de archivos, que pueden evitar la aplicación de morir durante este proceso, pero es que la forma correcta de hacer esto? Siento que me falta algo para evitar lanzar un error FD malo en primer lugar.
<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>
Esto es correcto, pero no estaba disponible cuando presenté esta pregunta. :) Archivé el Nodo número 2453 (https://github.com/joyent/node/issues/2453) y se agregó el evento 'cerrar'. – dec