diff --git a/lib/cluster.js b/lib/cluster.js index 08230ad4aa882c..39fed1c71a06ba 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -625,12 +625,26 @@ function workerInit() { Worker.prototype.disconnect = function() { this.suicide = true; + var waitingHandles = 0; + + function checkRemainingHandles() { + waitingHandles--; + if (waitingHandles === 0) { + process.disconnect(); + } + } + for (var key in handles) { var handle = handles[key]; delete handles[key]; - handle.close(); + waitingHandles++; + handle.owner.close(checkRemainingHandles); } - process.disconnect(); + + if (waitingHandles === 0) { + process.disconnect(); + } + }; Worker.prototype.destroy = function() { diff --git a/test/parallel/test-cluster-worker-wait-server-close.js b/test/parallel/test-cluster-worker-wait-server-close.js new file mode 100644 index 00000000000000..a3d29cec1715cd --- /dev/null +++ b/test/parallel/test-cluster-worker-wait-server-close.js @@ -0,0 +1,63 @@ +var common = require('../common'); +var assert = require('assert'); +var cluster = require('cluster'); +var net = require('net'); + +if (cluster.isWorker) { + net.createServer(function(socket) { + // Wait for any data, then close connection + socket.on('data', socket.end.bind(socket)); + }).listen(common.PORT, common.localhostIPv4); +} else if (cluster.isMaster) { + + var connectionDone; + var checks = { + disconnectedOnClientsEnd: false, + workerDied: false + }; + + // helper function to check if a process is alive + var alive = function(pid) { + try { + process.kill(pid, 0); + return true; + } catch (e) { + return false; + } + }; + + // start worker + var worker = cluster.fork(); + + // Disconnect worker when it is ready + worker.once('listening', function() { + net.createConnection(common.PORT, common.localhostIPv4, function() { + var socket = this; + setTimeout(function() { + worker.disconnect(); + setTimeout(function() { + socket.write('.'); + connectionDone = true; + }, 1000); + }, 1000); + }); + }); + + // Check worker events and properties + worker.once('disconnect', function() { + checks.disconnectedOnClientsEnd = connectionDone; + }); + + // Check that the worker died + worker.once('exit', function() { + checks.workerDied = !alive(worker.process.pid); + process.nextTick(function() { + process.exit(0); + }); + }); + + process.once('exit', function() { + assert.ok(checks.disconnectedOnClientsEnd, 'The worker disconnected before all clients are ended'); + assert.ok(checks.workerDied, 'The worker did not die'); + }); +}