From 9c0a1b8cfcda6c9cb42e3632127928479d3aebeb Mon Sep 17 00:00:00 2001 From: Oleg Elifantiev Date: Tue, 2 Jun 2015 23:23:31 +0300 Subject: [PATCH] cluster: wait on servers closing before disconnect Before this, cluster behaves not the way it is documented. When disconnect is triggered, worker must wait for every server is closed before doing disconnect actually. Reviewed-By: Sam Roberts Reviewed-By: Colin Ihrig PR-URL: https://github.com/nodejs/io.js/pull/1400 Fixes: https://github.com/nodejs/io.js/issues/1305 --- lib/cluster.js | 18 +++++++- .../test-cluster-worker-wait-server-close.js | 42 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-cluster-worker-wait-server-close.js diff --git a/lib/cluster.js b/lib/cluster.js index ca1005b738068f..bb4b60a2fc489e 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -627,12 +627,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..0f1836c7eccaa2 --- /dev/null +++ b/test/parallel/test-cluster-worker-wait-server-close.js @@ -0,0 +1,42 @@ +'use strict'; + +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 ok; + + // 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; + worker.disconnect(); + setTimeout(function() { + socket.write('.'); + connectionDone = true; + }, 1000); + }); + }); + + // Check worker events and properties + worker.once('disconnect', function() { + assert.ok(connectionDone, 'disconnect should occur after socket close'); + ok = true; + }); + + process.once('exit', function() { + assert.ok(ok); + }); +}