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 {
const wrapped = workerThreadSetup.wrapProcessMethods(rawMethods);
process.abort = workerThreadSetup.unavailable('process.abort()');
process.chdir = workerThreadSetup.unavailable('process.chdir()');
process.umask = wrapped.umask;
}
@ -148,6 +150,14 @@ if (credentials.implementsPosixCredentials) {
process.seteuid = wrapped.seteuid;
process.setgid = wrapped.setgid;
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:
// process.send(), process.channel, process.connected,
// process.disconnect()
if (isMainThread && process.env.NODE_CHANNEL_FD) {
if (process.env.NODE_CHANNEL_FD) {
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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,12 @@
'use strict';
const common = require('../common');
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);
w.on('message', common.mustCall((message) => {
assert.strictEqual(message, true);
@ -21,14 +24,25 @@ if (isMainThread) {
assert.strictEqual(process.debugPort, before);
}
assert.strictEqual('abort' in process, false);
assert.strictEqual('chdir' in process, false);
assert.strictEqual('setuid' in process, false);
assert.strictEqual('seteuid' in process, false);
assert.strictEqual('setgid' in process, false);
assert.strictEqual('setegid' in process, false);
assert.strictEqual('setgroups' in process, false);
assert.strictEqual('initgroups' in process, false);
const stubs = ['abort', 'chdir', 'send', 'disconnect'];
if (!common.isWindows) {
stubs.push('setuid', 'seteuid', 'setgid',
'setegid', 'setgroups', 'initgroups');
}
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('_stopProfilerIdleNotifier' in process, false);