Skip to content

Commit

Permalink
cluster: wait for all servers closing before disconnect
Browse files Browse the repository at this point in the history
Fix for iojs/io,js#1305
Before this, cluster bahaves not the way it is docummented
Then disconnect is triggered, worker must wait for every server is closed
before doing disconnect actually.

See test case and discussion in the above mentioned issue
  • Loading branch information
Olegas committed Jun 2, 2015
1 parent 93a1a07 commit 35854ae
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
18 changes: 16 additions & 2 deletions lib/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
63 changes: 63 additions & 0 deletions test/parallel/test-cluster-worker-wait-server-close.js
Original file line number Diff line number Diff line change
@@ -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');
});
}

0 comments on commit 35854ae

Please sign in to comment.