Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cluster: reset handle index on close #6981

Merged
merged 1 commit into from
May 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions lib/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,18 +564,18 @@ function workerInit() {

// obj is a net#Server or a dgram#Socket object.
cluster._getServer = function(obj, options, cb) {
const key = [ options.address,
options.port,
options.addressType,
options.fd ].join(':');
if (indexes[key] === undefined)
indexes[key] = 0;
const indexesKey = [ options.address,
options.port,
options.addressType,
options.fd ].join(':');
if (indexes[indexesKey] === undefined)
indexes[indexesKey] = 0;
else
indexes[key]++;
indexes[indexesKey]++;

const message = util._extend({
act: 'queryServer',
index: indexes[key],
index: indexes[indexesKey],
data: null
}, options);

Expand All @@ -585,9 +585,9 @@ function workerInit() {
if (obj._setServerData) obj._setServerData(reply.data);

if (handle)
shared(reply, handle, cb); // Shared listen socket.
shared(reply, handle, indexesKey, cb); // Shared listen socket.
else
rr(reply, cb); // Round-robin.
rr(reply, indexesKey, cb); // Round-robin.
});
obj.once('listening', function() {
cluster.worker.state = 'listening';
Expand All @@ -599,14 +599,15 @@ function workerInit() {
};

// Shared listen socket.
function shared(message, handle, cb) {
function shared(message, handle, indexesKey, cb) {
var key = message.key;
// Monkey-patch the close() method so we can keep track of when it's
// closed. Avoids resource leaks when the handle is short-lived.
var close = handle.close;
handle.close = function() {
send({ act: 'close', key: key });
delete handles[key];
delete indexes[indexesKey];
return close.apply(this, arguments);
};
assert(handles[key] === undefined);
Expand All @@ -615,7 +616,7 @@ function workerInit() {
}

// Round-robin. Master distributes handles across workers.
function rr(message, cb) {
function rr(message, indexesKey, cb) {
if (message.errno)
return cb(message.errno, null);

Expand All @@ -636,6 +637,7 @@ function workerInit() {
if (key === undefined) return;
send({ act: 'close', key: key });
delete handles[key];
delete indexes[indexesKey];
key = undefined;
}

Expand Down
37 changes: 37 additions & 0 deletions test/parallel/test-cluster-server-restart-none.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');

cluster.schedulingPolicy = cluster.SCHED_NONE;

if (cluster.isMaster) {
const worker1 = cluster.fork();
worker1.on('listening', common.mustCall(() => {
const worker2 = cluster.fork();
worker2.on('exit', (code, signal) => {
assert.strictEqual(code, 0, 'worker2 did not exit normally');
assert.strictEqual(signal, null, 'worker2 did not exit normally');
worker1.disconnect();
});
}));

worker1.on('exit', common.mustCall((code, signal) => {
assert.strictEqual(code, 0, 'worker1 did not exit normally');
assert.strictEqual(signal, null, 'worker1 did not exit normally');
}));
} else {
const net = require('net');
const server = net.createServer();
server.listen(common.PORT, common.mustCall(() => {
if (cluster.worker.id === 2) {
server.close(() => {
server.listen(common.PORT, common.mustCall(() => {
server.close(() => {
process.disconnect();
});
}));
});
}
}));
}
37 changes: 37 additions & 0 deletions test/parallel/test-cluster-server-restart-rr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');

cluster.schedulingPolicy = cluster.SCHED_RR;

if (cluster.isMaster) {
const worker1 = cluster.fork();
worker1.on('listening', common.mustCall(() => {
const worker2 = cluster.fork();
worker2.on('exit', (code, signal) => {
assert.strictEqual(code, 0, 'worker2 did not exit normally');
assert.strictEqual(signal, null, 'worker2 did not exit normally');
worker1.disconnect();
});
}));

worker1.on('exit', common.mustCall((code, signal) => {
assert.strictEqual(code, 0, 'worker1 did not exit normally');
assert.strictEqual(signal, null, 'worker1 did not exit normally');
}));
} else {
const net = require('net');
const server = net.createServer();
server.listen(common.PORT, common.mustCall(() => {
if (cluster.worker.id === 2) {
server.close(() => {
server.listen(common.PORT, common.mustCall(() => {
server.close(() => {
process.disconnect();
});
}));
});
}
}));
}