Skip to content

Commit

Permalink
lib: do not crash using workers with disabled shared array buffers
Browse files Browse the repository at this point in the history
This allows the repl to function normally while using the
`--no-harmony-sharedarraybuffer` V8 flag.
It also fixes using workers while using the
`--no-harmony-atomics` V8 flag.

Fixes: #39717

Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de>

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
PR-URL: #41023
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
2 people authored and danielleadams committed Apr 3, 2023
1 parent 847d740 commit 46a22ab
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 17 deletions.
9 changes: 8 additions & 1 deletion benchmark/worker/atomics-wait.js
@@ -1,5 +1,12 @@
'use strict';
/* global SharedArrayBuffer */

if (typeof SharedArrayBuffer === 'undefined') {
throw new Error('SharedArrayBuffers must be enabled to run this benchmark');
}

if (typeof Atomics === 'undefined') {
throw new Error('Atomics must be enabled to run this benchmark');
}

const common = require('../common.js');
const bench = common.createBenchmark(main, {
Expand Down
35 changes: 20 additions & 15 deletions lib/internal/main/worker_thread.js
Expand Up @@ -10,7 +10,10 @@ const {
ObjectDefineProperty,
PromisePrototypeThen,
RegExpPrototypeExec,
globalThis: { Atomics },
globalThis: {
Atomics,
SharedArrayBuffer,
},
} = primordials;

const {
Expand Down Expand Up @@ -105,21 +108,23 @@ port.on('message', (message) => {

require('internal/worker').assignEnvironmentData(environmentData);

// The counter is only passed to the workers created by the main thread, not
// to workers created by other workers.
let cachedCwd = '';
let lastCounter = -1;
const originalCwd = process.cwd;

process.cwd = function() {
const currentCounter = Atomics.load(cwdCounter, 0);
if (currentCounter === lastCounter)
if (SharedArrayBuffer !== undefined && Atomics !== undefined) {
// The counter is only passed to the workers created by the main thread,
// not to workers created by other workers.
let cachedCwd = '';
let lastCounter = -1;
const originalCwd = process.cwd;

process.cwd = function() {
const currentCounter = Atomics.load(cwdCounter, 0);
if (currentCounter === lastCounter)
return cachedCwd;
lastCounter = currentCounter;
cachedCwd = originalCwd();
return cachedCwd;
lastCounter = currentCounter;
cachedCwd = originalCwd();
return cachedCwd;
};
workerIo.sharedCwdCounter = cwdCounter;
};
workerIo.sharedCwdCounter = cwdCounter;
}

if (manifestSrc) {
require('internal/process/policy').setup(manifestSrc, manifestURL);
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/worker.js
Expand Up @@ -91,7 +91,9 @@ let cwdCounter;

const environmentData = new SafeMap();

if (isMainThread) {
// SharedArrayBuffers can be disabled with --no-harmony-sharedarraybuffer.
// Atomics can be disabled with --no-harmony-atomics.
if (isMainThread && SharedArrayBuffer !== undefined && Atomics !== undefined) {
cwdCounter = new Uint32Array(new SharedArrayBuffer(4));
const originalChdir = process.chdir;
process.chdir = function(path) {
Expand Down
21 changes: 21 additions & 0 deletions test/parallel/test-worker-no-atomics.js
@@ -0,0 +1,21 @@
// Flags: --no-harmony-atomics

'use strict';

const common = require('../common');
const assert = require('assert');
const { Worker } = require('worker_threads');

// Regression test for https://github.com/nodejs/node/issues/39717.

// 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;
const w = new Worker(__filename);

w.on('exit', common.mustCall((status) => {
assert.strictEqual(status, 2);
}));
} else {
process.exit(2);
}
21 changes: 21 additions & 0 deletions test/parallel/test-worker-no-sab.js
@@ -0,0 +1,21 @@
// Flags: --no-harmony-sharedarraybuffer

'use strict';

const common = require('../common');
const assert = require('assert');
const { Worker } = require('worker_threads');

// Regression test for https://github.com/nodejs/node/issues/39717.

// 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;
const w = new Worker(__filename);

w.on('exit', common.mustCall((status) => {
assert.strictEqual(status, 2);
}));
} else {
process.exit(2);
}

0 comments on commit 46a22ab

Please sign in to comment.