Skip to content

Commit 0c29436

Browse files
committed
cluster: reset handle index on close
It allows reopening a server after it has been closed. Fixes: #6693 PR-URL: #6981 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Ron Korving <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent e916218 commit 0c29436

File tree

3 files changed

+88
-12
lines changed

3 files changed

+88
-12
lines changed

lib/cluster.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -564,18 +564,18 @@ function workerInit() {
564564

565565
// obj is a net#Server or a dgram#Socket object.
566566
cluster._getServer = function(obj, options, cb) {
567-
const key = [ options.address,
568-
options.port,
569-
options.addressType,
570-
options.fd ].join(':');
571-
if (indexes[key] === undefined)
572-
indexes[key] = 0;
567+
const indexesKey = [ options.address,
568+
options.port,
569+
options.addressType,
570+
options.fd ].join(':');
571+
if (indexes[indexesKey] === undefined)
572+
indexes[indexesKey] = 0;
573573
else
574-
indexes[key]++;
574+
indexes[indexesKey]++;
575575

576576
const message = util._extend({
577577
act: 'queryServer',
578-
index: indexes[key],
578+
index: indexes[indexesKey],
579579
data: null
580580
}, options);
581581

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

587587
if (handle)
588-
shared(reply, handle, cb); // Shared listen socket.
588+
shared(reply, handle, indexesKey, cb); // Shared listen socket.
589589
else
590-
rr(reply, cb); // Round-robin.
590+
rr(reply, indexesKey, cb); // Round-robin.
591591
});
592592
obj.once('listening', function() {
593593
cluster.worker.state = 'listening';
@@ -599,14 +599,15 @@ function workerInit() {
599599
};
600600

601601
// Shared listen socket.
602-
function shared(message, handle, cb) {
602+
function shared(message, handle, indexesKey, cb) {
603603
var key = message.key;
604604
// Monkey-patch the close() method so we can keep track of when it's
605605
// closed. Avoids resource leaks when the handle is short-lived.
606606
var close = handle.close;
607607
handle.close = function() {
608608
send({ act: 'close', key: key });
609609
delete handles[key];
610+
delete indexes[indexesKey];
610611
return close.apply(this, arguments);
611612
};
612613
assert(handles[key] === undefined);
@@ -615,7 +616,7 @@ function workerInit() {
615616
}
616617

617618
// Round-robin. Master distributes handles across workers.
618-
function rr(message, cb) {
619+
function rr(message, indexesKey, cb) {
619620
if (message.errno)
620621
return cb(message.errno, null);
621622

@@ -636,6 +637,7 @@ function workerInit() {
636637
if (key === undefined) return;
637638
send({ act: 'close', key: key });
638639
delete handles[key];
640+
delete indexes[indexesKey];
639641
key = undefined;
640642
}
641643

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const cluster = require('cluster');
5+
6+
cluster.schedulingPolicy = cluster.SCHED_NONE;
7+
8+
if (cluster.isMaster) {
9+
const worker1 = cluster.fork();
10+
worker1.on('listening', common.mustCall(() => {
11+
const worker2 = cluster.fork();
12+
worker2.on('exit', (code, signal) => {
13+
assert.strictEqual(code, 0, 'worker2 did not exit normally');
14+
assert.strictEqual(signal, null, 'worker2 did not exit normally');
15+
worker1.disconnect();
16+
});
17+
}));
18+
19+
worker1.on('exit', common.mustCall((code, signal) => {
20+
assert.strictEqual(code, 0, 'worker1 did not exit normally');
21+
assert.strictEqual(signal, null, 'worker1 did not exit normally');
22+
}));
23+
} else {
24+
const net = require('net');
25+
const server = net.createServer();
26+
server.listen(common.PORT, common.mustCall(() => {
27+
if (cluster.worker.id === 2) {
28+
server.close(() => {
29+
server.listen(common.PORT, common.mustCall(() => {
30+
server.close(() => {
31+
process.disconnect();
32+
});
33+
}));
34+
});
35+
}
36+
}));
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const cluster = require('cluster');
5+
6+
cluster.schedulingPolicy = cluster.SCHED_RR;
7+
8+
if (cluster.isMaster) {
9+
const worker1 = cluster.fork();
10+
worker1.on('listening', common.mustCall(() => {
11+
const worker2 = cluster.fork();
12+
worker2.on('exit', (code, signal) => {
13+
assert.strictEqual(code, 0, 'worker2 did not exit normally');
14+
assert.strictEqual(signal, null, 'worker2 did not exit normally');
15+
worker1.disconnect();
16+
});
17+
}));
18+
19+
worker1.on('exit', common.mustCall((code, signal) => {
20+
assert.strictEqual(code, 0, 'worker1 did not exit normally');
21+
assert.strictEqual(signal, null, 'worker1 did not exit normally');
22+
}));
23+
} else {
24+
const net = require('net');
25+
const server = net.createServer();
26+
server.listen(common.PORT, common.mustCall(() => {
27+
if (cluster.worker.id === 2) {
28+
server.close(() => {
29+
server.listen(common.PORT, common.mustCall(() => {
30+
server.close(() => {
31+
process.disconnect();
32+
});
33+
}));
34+
});
35+
}
36+
}));
37+
}

0 commit comments

Comments
 (0)