Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 08a6a61

Browse filesBrowse files
theanarkhjuanarbol
authored andcommitted
src,lib: the handle keeps loop alive in cluster rr mode
PR-URL: #46161 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
1 parent 3ce39bb commit 08a6a61
Copy full SHA for 08a6a61

File tree

Expand file treeCollapse file tree

4 files changed

+88
-7
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+88
-7
lines changed
Open diff view settings
Collapse file

‎lib/internal/cluster/child.js‎

Copy file name to clipboardExpand all lines: lib/internal/cluster/child.js
+27-7Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ const EventEmitter = require('events');
1515
const { owner_symbol } = require('internal/async_hooks').symbols;
1616
const Worker = require('internal/cluster/worker');
1717
const { internal, sendHelper } = require('internal/cluster/utils');
18+
const { TIMEOUT_MAX } = require('internal/timers');
19+
const { setInterval, clearInterval } = require('timers');
20+
1821
const cluster = new EventEmitter();
1922
const handles = new SafeMap();
2023
const indexes = new SafeMap();
@@ -160,6 +163,21 @@ function rr(message, { indexesKey, index }, cb) {
160163

161164
let key = message.key;
162165

166+
let fakeHandle = null;
167+
168+
function ref() {
169+
if (!fakeHandle) {
170+
fakeHandle = setInterval(noop, TIMEOUT_MAX);
171+
}
172+
}
173+
174+
function unref() {
175+
if (fakeHandle) {
176+
clearInterval(fakeHandle);
177+
fakeHandle = null;
178+
}
179+
}
180+
163181
function listen(backlog) {
164182
// TODO(bnoordhuis) Send a message to the primary that tells it to
165183
// update the backlog size. The actual backlog should probably be
@@ -175,7 +193,11 @@ function rr(message, { indexesKey, index }, cb) {
175193
// the primary.
176194
if (key === undefined)
177195
return;
178-
196+
unref();
197+
// If the handle is the last handle in process,
198+
// the parent process will delete the handle when worker process exits.
199+
// So it is ok if the close message get lost.
200+
// See the comments of https://github.com/nodejs/node/pull/46161
179201
send({ act: 'close', key });
180202
handles.delete(key);
181203
removeIndexesKey(indexesKey, index);
@@ -189,12 +211,10 @@ function rr(message, { indexesKey, index }, cb) {
189211
return 0;
190212
}
191213

192-
// Faux handle. Mimics a TCPWrap with just enough fidelity to get away
193-
// with it. Fools net.Server into thinking that it's backed by a real
194-
// handle. Use a noop function for ref() and unref() because the control
195-
// channel is going to keep the worker alive anyway.
196-
const handle = { close, listen, ref: noop, unref: noop };
197-
214+
// Faux handle. net.Server is not associated with handle,
215+
// so we control its state(ref or unref) by setInterval.
216+
const handle = { close, listen, ref, unref };
217+
handle.ref();
198218
if (message.sockname) {
199219
handle.getsockname = getsockname; // TCP handles only.
200220
}
Collapse file
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const cluster = require('cluster');
5+
const net = require('net');
6+
7+
cluster.schedulingPolicy = cluster.SCHED_RR;
8+
9+
if (cluster.isPrimary) {
10+
const worker = cluster.fork();
11+
worker.on('exit', common.mustCall());
12+
} else {
13+
const server = net.createServer(common.mustNotCall());
14+
server.listen(0, common.mustCall(() => {
15+
process.channel.unref();
16+
server.close();
17+
}));
18+
}
Collapse file
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const cluster = require('cluster');
5+
const net = require('net');
6+
const assert = require('assert');
7+
8+
cluster.schedulingPolicy = cluster.SCHED_RR;
9+
10+
if (cluster.isPrimary) {
11+
let exited = false;
12+
const worker = cluster.fork();
13+
worker.on('exit', () => {
14+
exited = true;
15+
});
16+
setTimeout(() => {
17+
assert.ok(!exited);
18+
worker.kill();
19+
}, 3000);
20+
} else {
21+
const server = net.createServer(common.mustNotCall());
22+
server.listen(0, common.mustCall(() => process.channel.unref()));
23+
}
Collapse file
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const cluster = require('cluster');
5+
const net = require('net');
6+
7+
cluster.schedulingPolicy = cluster.SCHED_RR;
8+
9+
if (cluster.isPrimary) {
10+
const worker = cluster.fork();
11+
worker.on('exit', common.mustCall());
12+
} else {
13+
const server = net.createServer(common.mustNotCall());
14+
server.listen(0, common.mustCall(() => {
15+
server.ref();
16+
server.unref();
17+
process.channel.unref();
18+
}));
19+
server.unref();
20+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.