Skip to content

Commit d7ed125

Browse files
cjihrigtargos
authored andcommitted
process: stub unsupported worker methods
Some process methods are not supported in workers. This commit adds stubs that throw more informative errors. PR-URL: #25587 Fixes: #25448 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 01bb7b7 commit d7ed125

7 files changed

+83
-25
lines changed

lib/internal/bootstrap/node.js

+28-2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ if (isMainThread) {
8484
} else {
8585
const wrapped = workerThreadSetup.wrapProcessMethods(rawMethods);
8686

87+
process.abort = workerThreadSetup.unavailable('process.abort()');
88+
process.chdir = workerThreadSetup.unavailable('process.chdir()');
8789
process.umask = wrapped.umask;
8890
}
8991

@@ -148,6 +150,14 @@ if (credentials.implementsPosixCredentials) {
148150
process.seteuid = wrapped.seteuid;
149151
process.setgid = wrapped.setgid;
150152
process.setuid = wrapped.setuid;
153+
} else {
154+
process.initgroups =
155+
workerThreadSetup.unavailable('process.initgroups()');
156+
process.setgroups = workerThreadSetup.unavailable('process.setgroups()');
157+
process.setegid = workerThreadSetup.unavailable('process.setegid()');
158+
process.seteuid = workerThreadSetup.unavailable('process.seteuid()');
159+
process.setgid = workerThreadSetup.unavailable('process.setgid()');
160+
process.setuid = workerThreadSetup.unavailable('process.setuid()');
151161
}
152162
}
153163

@@ -174,8 +184,24 @@ if (config.hasInspector) {
174184
// This attaches some internal event listeners and creates:
175185
// process.send(), process.channel, process.connected,
176186
// process.disconnect()
177-
if (isMainThread && process.env.NODE_CHANNEL_FD) {
178-
mainThreadSetup.setupChildProcessIpcChannel();
187+
if (process.env.NODE_CHANNEL_FD) {
188+
if (ownsProcessState) {
189+
mainThreadSetup.setupChildProcessIpcChannel();
190+
} else {
191+
Object.defineProperty(process, 'channel', {
192+
enumerable: false,
193+
get: workerThreadSetup.unavailable('process.channel')
194+
});
195+
196+
Object.defineProperty(process, 'connected', {
197+
enumerable: false,
198+
get: workerThreadSetup.unavailable('process.connected')
199+
});
200+
201+
process.send = workerThreadSetup.unavailable('process.send()');
202+
process.disconnect =
203+
workerThreadSetup.unavailable('process.disconnect()');
204+
}
179205
}
180206

181207
const browserGlobals = !process._noBrowserGlobals;

lib/internal/process/worker_thread_only.js

+10
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,17 @@ function wrapProcessMethods(binding) {
4545
return { umask };
4646
}
4747

48+
function unavailable(name) {
49+
function unavailableInWorker() {
50+
throw new ERR_WORKER_UNSUPPORTED_OPERATION(name);
51+
}
52+
53+
unavailableInWorker.disabled = true;
54+
return unavailableInWorker;
55+
}
56+
4857
module.exports = {
4958
initializeWorkerStdio,
59+
unavailable,
5060
wrapProcessMethods
5161
};

test/parallel/test-process-euid-egid.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@
33
const common = require('../common');
44
const assert = require('assert');
55

6-
if (common.isWindows || !common.isMainThread) {
7-
if (common.isMainThread) {
8-
assert.strictEqual(process.geteuid, undefined);
9-
assert.strictEqual(process.getegid, undefined);
10-
}
6+
if (common.isWindows) {
7+
assert.strictEqual(process.geteuid, undefined);
8+
assert.strictEqual(process.getegid, undefined);
119
assert.strictEqual(process.seteuid, undefined);
1210
assert.strictEqual(process.setegid, undefined);
1311
return;
1412
}
1513

14+
if (!common.isMainThread)
15+
return;
16+
1617
assert.throws(() => {
1718
process.seteuid({});
1819
}, {

test/parallel/test-process-initgroups.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
const common = require('../common');
33
const assert = require('assert');
44

5-
if (common.isWindows || !common.isMainThread) {
5+
if (common.isWindows) {
66
assert.strictEqual(process.initgroups, undefined);
77
return;
88
}
99

10+
if (!common.isMainThread)
11+
return;
12+
1013
[undefined, null, true, {}, [], () => {}].forEach((val) => {
1114
assert.throws(
1215
() => {

test/parallel/test-process-setgroups.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
const common = require('../common');
33
const assert = require('assert');
44

5-
if (common.isWindows || !common.isMainThread) {
5+
if (common.isWindows) {
66
assert.strictEqual(process.setgroups, undefined);
77
return;
88
}
99

10+
if (!common.isMainThread)
11+
return;
12+
1013
assert.throws(
1114
() => {
1215
process.setgroups();

test/parallel/test-process-uid-gid.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,18 @@ const common = require('../common');
2424

2525
const assert = require('assert');
2626

27-
if (common.isWindows || !common.isMainThread) {
28-
// uid/gid functions are POSIX only, setters are main-thread only.
29-
if (common.isMainThread) {
30-
assert.strictEqual(process.getuid, undefined);
31-
assert.strictEqual(process.getgid, undefined);
32-
}
27+
if (common.isWindows) {
28+
// uid/gid functions are POSIX only.
29+
assert.strictEqual(process.getuid, undefined);
30+
assert.strictEqual(process.getgid, undefined);
3331
assert.strictEqual(process.setuid, undefined);
3432
assert.strictEqual(process.setgid, undefined);
3533
return;
3634
}
3735

36+
if (!common.isMainThread)
37+
return;
38+
3839
assert.throws(() => {
3940
process.setuid({});
4041
}, {

test/parallel/test-worker-unsupported-things.js

+24-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
'use strict';
22
const common = require('../common');
33
const assert = require('assert');
4-
const { Worker, isMainThread, parentPort } = require('worker_threads');
4+
const { Worker, parentPort } = require('worker_threads');
55

6-
if (isMainThread) {
6+
// Do not use isMainThread so that this test itself can be run inside a Worker.
7+
if (!process.env.HAS_STARTED_WORKER) {
8+
process.env.HAS_STARTED_WORKER = 1;
9+
process.env.NODE_CHANNEL_FD = 'foo'; // Make worker think it has IPC.
710
const w = new Worker(__filename);
811
w.on('message', common.mustCall((message) => {
912
assert.strictEqual(message, true);
@@ -21,14 +24,25 @@ if (isMainThread) {
2124
assert.strictEqual(process.debugPort, before);
2225
}
2326

24-
assert.strictEqual('abort' in process, false);
25-
assert.strictEqual('chdir' in process, false);
26-
assert.strictEqual('setuid' in process, false);
27-
assert.strictEqual('seteuid' in process, false);
28-
assert.strictEqual('setgid' in process, false);
29-
assert.strictEqual('setegid' in process, false);
30-
assert.strictEqual('setgroups' in process, false);
31-
assert.strictEqual('initgroups' in process, false);
27+
const stubs = ['abort', 'chdir', 'send', 'disconnect'];
28+
29+
if (!common.isWindows) {
30+
stubs.push('setuid', 'seteuid', 'setgid',
31+
'setegid', 'setgroups', 'initgroups');
32+
}
33+
34+
stubs.forEach((fn) => {
35+
assert.strictEqual(process[fn].disabled, true);
36+
assert.throws(() => {
37+
process[fn]();
38+
}, { code: 'ERR_WORKER_UNSUPPORTED_OPERATION' });
39+
});
40+
41+
['channel', 'connected'].forEach((fn) => {
42+
assert.throws(() => {
43+
process[fn];
44+
}, { code: 'ERR_WORKER_UNSUPPORTED_OPERATION' });
45+
});
3246

3347
assert.strictEqual('_startProfilerIdleNotifier' in process, false);
3448
assert.strictEqual('_stopProfilerIdleNotifier' in process, false);

0 commit comments

Comments
 (0)