Sto provando a creare una piattaforma per l'auto-distribuzione delle applicazioni che compongo in NodeJS. Ogni applicazione può essere avviata e arrestata da un pannello di controllo che gestisce queste operazioni. Il pannello di controllo fa le seguenti cose quando viene avviata un'applicazione:Come smaltire correttamente gli handle dai processi secondari
- richiede una maniglia da una porta-legante che esegue come root. Questo port-binder è un figlio biforcuto del pannello di controllo.
- Ora il pannello di controllo ascolta le richieste su questa porta. Una volta ricevuta una richiesta, invia l'handle del socket client all'applicazione che sta ascoltando l'evento 'message' per le nuove richieste.
- Una volta segnalata l'applicazione, il pannello di controllo rilascia tutto il controllo sulla richiesta e sulla presa.
- L'applicazione fa ciò che deve fare e rilascia e chiude anche la richiesta e il socket.
Questa configurazione funziona bene, tranne quando si tenta di abbattere un server che non è più necessario. Anche se il server emette l'evento "close", accetta comunque la connessione, che alla fine si interrompe perché non vi è più alcun binding di richiesta.
Suppongo che ci sia un handle che non è stato rilasciato correttamente e quindi mantiene il server sveglio.
Port legante: pannello
var options = {
http: require('http'),
https: require('https')
};
process.on('message',function(data, handle) {
var port = data.port,
type = data.type,
server;
server = options[type].createServer();
server.once('error', function(err) {
process.send({success: false, port: port, error: err});
});
server.listen(port,function(){
var handle = server._handle;
process.send({success: true, port: port}, handle);
server.close();
handle.close();
server._handle = null;
handle = null;
server.removeAllListeners();
});
});
controllo:
var cp = require('child_process'),
app,
types = {
http: require('http'),
https: require('https')
},
binder = cp.fork('./portbinder');
binder.on('message', function(data, handle) {
var server = types['http'].createServer(handler);
server.once('close', function() {
server._handle = null;
handle = null;
});
server.listen(handle);
});
function handler(req, resp) {
app = app || cp.fork('./application'),
socket = resp.socket,
_handle = socket._handle,
_req = {},
_resp = {},
_socket = {};
// Copy transferable fields.
for(i in req) {
if(typeof req[i] != 'function' && i != 'socket' && i != 'connection' && i != 'client') {
_req[i] = req[i];
}
}
for(i in resp) {
if(typeof resp[i] != 'function' && i != 'socket' && i != 'connection' && i != 'client') {
_resp[i] = resp[i];
}
}
for(i in socket) {
if(typeof socket[i] != 'function' &&
i != '_handle' && i != '_httpMessage' &&
i != '_idlePrev' && i != '_idleNext' && i != 'server') {
_socket[i] = socket[i];
}
}
// Send request to application.
app.send({
type: 'request',
data: {
req: _req,
resp: _resp,
socket: _socket
}
}, _handle);
// Release the handle here without sending anything to the browser.
socket._write = function() {};
resp.end();
socket.destroy();
socket._handle = null;
_handle = null;
};
Applicazioni:
Come si può vedere che sto cercando su null e staccare tutte le proprietà _handle I avere, ma l'handle del server non interrompe l'ascolto sulla porta. Quando faccio sì che il pannello di controllo abbia un'eccezione non rilevata, si blocca e anche il raccoglitore di porte fa altrettanto. Ma il processo del nodo dell'applicazione non si chiude e la porta rimane vincolata, quindi sto geussing che non sto rilasciando qualcosa correttamente, ma non riesco a trovarlo.
L'intera installazione funziona, non è semplicemente chiudere un server quando lo chiedo.
EDIT: ho probabilmente dovrebbe notare che sto usando node.js v0.5.10
Hai provato con v0.6.0? Credo che hanno aggiunto ulteriori funzionalità per il bambino processi –
v0.6.0 installato oggi, e il problema persiste. I documenti non descrivono nulla di nuovo, guarderò la fonte più tardi oggi, forse semplicemente non è documentato. –