Skip to content

Commit

Permalink
process: stub unsupported worker methods
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
cjihrig authored and targos committed Feb 10, 2019
1 parent 01bb7b7 commit d7ed125
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 25 deletions.
30 changes: 28 additions & 2 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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()');
}
}

Expand All @@ -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) {
mainThreadSetup.setupChildProcessIpcChannel();
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;
Expand Down
10 changes: 10 additions & 0 deletions lib/internal/process/worker_thread_only.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
11 changes: 6 additions & 5 deletions test/parallel/test-process-euid-egid.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
const common = require('../common');
const assert = require('assert');

if (common.isWindows || !common.isMainThread) {
if (common.isMainThread) {
assert.strictEqual(process.geteuid, undefined);
assert.strictEqual(process.getegid, undefined);
}
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({});
}, {
Expand Down
5 changes: 4 additions & 1 deletion test/parallel/test-process-initgroups.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
() => {
Expand Down
5 changes: 4 additions & 1 deletion test/parallel/test-process-setgroups.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
13 changes: 7 additions & 6 deletions test/parallel/test-process-uid-gid.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
assert.strictEqual(process.getuid, undefined);
assert.strictEqual(process.getgid, undefined);
}
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({});
}, {
Expand Down
34 changes: 24 additions & 10 deletions test/parallel/test-worker-unsupported-things.js
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit d7ed125

Please sign in to comment.