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 5cf5956

Browse filesBrowse files
theanarkhRafaelGSS
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 9d55a1f commit 5cf5956
Copy full SHA for 5cf5956

File tree

Expand file treeCollapse file tree

4 files changed

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

4 files changed

+87
-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
+26-7Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ const { owner_symbol } = require('internal/async_hooks').symbols;
1616
const Worker = require('internal/cluster/worker');
1717
const { internal, sendHelper } = require('internal/cluster/utils');
1818
const { exitCodes: { kNoFailure } } = internalBinding('errors');
19+
const { TIMEOUT_MAX } = require('internal/timers');
20+
const { setInterval, clearInterval } = require('timers');
1921

2022
const cluster = new EventEmitter();
2123
const handles = new SafeMap();
@@ -162,6 +164,21 @@ function rr(message, { indexesKey, index }, cb) {
162164

163165
let key = message.key;
164166

167+
let fakeHandle = null;
168+
169+
function ref() {
170+
if (!fakeHandle) {
171+
fakeHandle = setInterval(noop, TIMEOUT_MAX);
172+
}
173+
}
174+
175+
function unref() {
176+
if (fakeHandle) {
177+
clearInterval(fakeHandle);
178+
fakeHandle = null;
179+
}
180+
}
181+
165182
function listen(backlog) {
166183
// TODO(bnoordhuis) Send a message to the primary that tells it to
167184
// update the backlog size. The actual backlog should probably be
@@ -177,7 +194,11 @@ function rr(message, { indexesKey, index }, cb) {
177194
// the primary.
178195
if (key === undefined)
179196
return;
180-
197+
unref();
198+
// If the handle is the last handle in process,
199+
// the parent process will delete the handle when worker process exits.
200+
// So it is ok if the close message get lost.
201+
// See the comments of https://github.com/nodejs/node/pull/46161
181202
send({ act: 'close', key });
182203
handles.delete(key);
183204
removeIndexesKey(indexesKey, index);
@@ -191,12 +212,10 @@ function rr(message, { indexesKey, index }, cb) {
191212
return 0;
192213
}
193214

194-
// Faux handle. Mimics a TCPWrap with just enough fidelity to get away
195-
// with it. Fools net.Server into thinking that it's backed by a real
196-
// handle. Use a noop function for ref() and unref() because the control
197-
// channel is going to keep the worker alive anyway.
198-
const handle = { close, listen, ref: noop, unref: noop };
199-
215+
// Faux handle. net.Server is not associated with handle,
216+
// so we control its state(ref or unref) by setInterval.
217+
const handle = { close, listen, ref, unref };
218+
handle.ref();
200219
if (message.sockname) {
201220
handle.getsockname = getsockname; // TCP handles only.
202221
}
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.