process: stub unsupported worker methods

Some process methods are not supported in workers. This commit
adds stubs that throw more informative errors.

PR-URL: https://github.com/nodejs/node/pull/25587
Fixes: https://github.com/nodejs/node/issues/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>
This commit is contained in:
cjihrig 2019-01-15 14:12:57 -05:00
parent 62b4796e36
commit 12b3cfcea6
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
7 changed files with 83 additions and 25 deletions

View File

@ -84,6 +84,8 @@ if (isMainThread) {
} else { } else {
const wrapped = workerThreadSetup.wrapProcessMethods(rawMethods); const wrapped = workerThreadSetup.wrapProcessMethods(rawMethods);
process.abort = workerThreadSetup.unavailable('process.abort()');
process.chdir = workerThreadSetup.unavailable('process.chdir()');
process.umask = wrapped.umask; process.umask = wrapped.umask;
} }
@ -148,6 +150,14 @@ if (credentials.implementsPosixCredentials) {
process.seteuid = wrapped.seteuid; process.seteuid = wrapped.seteuid;
process.setgid = wrapped.setgid; process.setgid = wrapped.setgid;
process.setuid = wrapped.setuid; process.setuid = wrapped.setuid;
} else {
process.initgroups =
workerThreadSetup.unavailable('process.initgroups()');
process.setgroups = workerThreadSetup.unavailable('process.setgroups()');
process.setegid = workerThreadSetup.unavailable('process.setegid()');
process.seteuid = workerThreadSetup.unavailable('process.seteuid()');
process.setgid = workerThreadSetup.unavailable('process.setgid()');
process.setuid = workerThreadSetup.unavailable('process.setuid()');
} }
} }
@ -174,8 +184,24 @@ if (config.hasInspector) {
// This attaches some internal event listeners and creates: // This attaches some internal event listeners and creates:
// process.send(), process.channel, process.connected, // process.send(), process.channel, process.connected,
// process.disconnect() // process.disconnect()
if (isMainThread && process.env.NODE_CHANNEL_FD) { if (process.env.NODE_CHANNEL_FD) {
mainThreadSetup.setupChildProcessIpcChannel(); if (ownsProcessState) {
mainThreadSetup.setupChildProcessIpcChannel();
} else {
Object.defineProperty(process, 'channel', {
enumerable: false,
get: workerThreadSetup.unavailable('process.channel')
});
Object.defineProperty(process, 'connected', {
enumerable: false,
get: workerThreadSetup.unavailable('process.connected')
});
process.send = workerThreadSetup.unavailable('process.send()');
process.disconnect =
workerThreadSetup.unavailable('process.disconnect()');
}
} }
const browserGlobals = !process._noBrowserGlobals; const browserGlobals = !process._noBrowserGlobals;

View File

@ -45,7 +45,17 @@ function wrapProcessMethods(binding) {
return { umask }; return { umask };
} }
function unavailable(name) {
function unavailableInWorker() {
throw new ERR_WORKER_UNSUPPORTED_OPERATION(name);
}
unavailableInWorker.disabled = true;
return unavailableInWorker;
}
module.exports = { module.exports = {
initializeWorkerStdio, initializeWorkerStdio,
unavailable,
wrapProcessMethods wrapProcessMethods
}; };

View File

@ -3,16 +3,17 @@
const common = require('../common'); const common = require('../common');
const assert = require('assert'); const assert = require('assert');
if (common.isWindows || !common.isMainThread) { if (common.isWindows) {
if (common.isMainThread) { assert.strictEqual(process.geteuid, undefined);
assert.strictEqual(process.geteuid, undefined); assert.strictEqual(process.getegid, undefined);
assert.strictEqual(process.getegid, undefined);
}
assert.strictEqual(process.seteuid, undefined); assert.strictEqual(process.seteuid, undefined);
assert.strictEqual(process.setegid, undefined); assert.strictEqual(process.setegid, undefined);
return; return;
} }
if (!common.isMainThread)
return;
assert.throws(() => { assert.throws(() => {
process.seteuid({}); process.seteuid({});
}, { }, {

View File

@ -2,11 +2,14 @@
const common = require('../common'); const common = require('../common');
const assert = require('assert'); const assert = require('assert');
if (common.isWindows || !common.isMainThread) { if (common.isWindows) {
assert.strictEqual(process.initgroups, undefined); assert.strictEqual(process.initgroups, undefined);
return; return;
} }
if (!common.isMainThread)
return;
[undefined, null, true, {}, [], () => {}].forEach((val) => { [undefined, null, true, {}, [], () => {}].forEach((val) => {
assert.throws( assert.throws(
() => { () => {

View File

@ -2,11 +2,14 @@
const common = require('../common'); const common = require('../common');
const assert = require('assert'); const assert = require('assert');
if (common.isWindows || !common.isMainThread) { if (common.isWindows) {
assert.strictEqual(process.setgroups, undefined); assert.strictEqual(process.setgroups, undefined);
return; return;
} }
if (!common.isMainThread)
return;
assert.throws( assert.throws(
() => { () => {
process.setgroups(); process.setgroups();

View File

@ -24,17 +24,18 @@ const common = require('../common');
const assert = require('assert'); const assert = require('assert');
if (common.isWindows || !common.isMainThread) { if (common.isWindows) {
// uid/gid functions are POSIX only, setters are main-thread only. // uid/gid functions are POSIX only.
if (common.isMainThread) { assert.strictEqual(process.getuid, undefined);
assert.strictEqual(process.getuid, undefined); assert.strictEqual(process.getgid, undefined);
assert.strictEqual(process.getgid, undefined);
}
assert.strictEqual(process.setuid, undefined); assert.strictEqual(process.setuid, undefined);
assert.strictEqual(process.setgid, undefined); assert.strictEqual(process.setgid, undefined);
return; return;
} }
if (!common.isMainThread)
return;
assert.throws(() => { assert.throws(() => {
process.setuid({}); process.setuid({});
}, { }, {

View File

@ -1,9 +1,12 @@
'use strict'; 'use strict';
const common = require('../common'); const common = require('../common');
const assert = require('assert'); const assert = require('assert');
const { Worker, isMainThread, parentPort } = require('worker_threads'); const { Worker, parentPort } = require('worker_threads');
if (isMainThread) { // Do not use isMainThread so that this test itself can be run inside a Worker.
if (!process.env.HAS_STARTED_WORKER) {
process.env.HAS_STARTED_WORKER = 1;
process.env.NODE_CHANNEL_FD = 'foo'; // Make worker think it has IPC.
const w = new Worker(__filename); const w = new Worker(__filename);
w.on('message', common.mustCall((message) => { w.on('message', common.mustCall((message) => {
assert.strictEqual(message, true); assert.strictEqual(message, true);
@ -21,14 +24,25 @@ if (isMainThread) {
assert.strictEqual(process.debugPort, before); assert.strictEqual(process.debugPort, before);
} }
assert.strictEqual('abort' in process, false); const stubs = ['abort', 'chdir', 'send', 'disconnect'];
assert.strictEqual('chdir' in process, false);
assert.strictEqual('setuid' in process, false); if (!common.isWindows) {
assert.strictEqual('seteuid' in process, false); stubs.push('setuid', 'seteuid', 'setgid',
assert.strictEqual('setgid' in process, false); 'setegid', 'setgroups', 'initgroups');
assert.strictEqual('setegid' in process, false); }
assert.strictEqual('setgroups' in process, false);
assert.strictEqual('initgroups' in process, false); stubs.forEach((fn) => {
assert.strictEqual(process[fn].disabled, true);
assert.throws(() => {
process[fn]();
}, { code: 'ERR_WORKER_UNSUPPORTED_OPERATION' });
});
['channel', 'connected'].forEach((fn) => {
assert.throws(() => {
process[fn];
}, { code: 'ERR_WORKER_UNSUPPORTED_OPERATION' });
});
assert.strictEqual('_startProfilerIdleNotifier' in process, false); assert.strictEqual('_startProfilerIdleNotifier' in process, false);
assert.strictEqual('_stopProfilerIdleNotifier' in process, false); assert.strictEqual('_stopProfilerIdleNotifier' in process, false);