Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

repl,worker: fix crash when SharedArrayBuffer disabled #39718

Closed
wants to merge 2 commits into from

Conversation

codebytere
Copy link
Member

Closes #39717.

It's possible for SharedArrayBuffers to be disabled with --no-harmony-sharedarraybuffer so we first need to check that this isn't the case before attempting to use them in the repl or the following crash occurs:

electron_node on git:a3d0cc7244 ❯ node --no-harmony-sharedarraybuffer       6:25PM
Welcome to Node.js v16.2.0.
Type ".help" for more information.
> snode:internal/readline/emitKeypressEvents:71
            throw err;
            ^

TypeError: SharedArrayBuffer is not a constructor
    at node:internal/worker:96:32
    at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
    at nativeModuleRequire (node:internal/bootstrap/loaders:341:14)
    at node:worker_threads:11:5
    at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
    at nativeModuleRequire (node:internal/bootstrap/loaders:341:14)
    at node:inspector:32:26
    at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
    at nativeModuleRequire (node:internal/bootstrap/loaders:341:14)
    at sendInspectorCommand (node:internal/util/inspector:14:21)

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. worker Issues and PRs related to Worker support. labels Aug 9, 2021
@codebytere codebytere added the repl Issues and PRs related to the REPL subsystem. label Aug 9, 2021
Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will likely break process.cwd() after changing the directory as it will return a cached value.
cwd() should also be protected in that case:

// 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;
};
workerIo.sharedCwdCounter = cwdCounter;

I am fine doing that, I just wonder if this is a common situation at all. AFAIK we mostly do not check all possible configurations and do not officially support them?

If we want to support the flag, we should also add a test (while such test can't really protect from other potential SharedArrayBuffer usages).

@codebytere
Copy link
Member Author

codebytere commented Aug 9, 2021

@BridgeAR happy to add a test - the other reason i'm interested in this in particular is because it's disabled in the web (see here) unless cross origin isolation is enabled, so this crashes the renderer process in some cases in Electron as well.

@targos
Copy link
Member

targos commented Aug 9, 2021

Is it repl or worker (the subsystem)?

@codebytere
Copy link
Member Author

@targos i guess sort of both? I can make it whatever you think would be preferable, but it'd be hit anytime anyone invoked repl.start() or when dealing with cwd in workers.

Copy link
Member

@Trott Trott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with lint fix and either a test or a comment (or both).

@targos
Copy link
Member

targos commented Aug 10, 2021

@targos i guess sort of both? I can make it whatever you think would be preferable, but it'd be hit anytime anyone invoked repl.start() or when dealing with cwd in workers.

@codebytere repl,worker: fix crash ... would work :)

@codebytere codebytere changed the title repl: fix crash when SharedArrayBuffer disabled repl,worker: fix crash when SharedArrayBuffer disabled Aug 10, 2021
@codebytere
Copy link
Member Author

@BridgeAR i think that should do it - let me know if you had something else in mind tho!

Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Just left a comment how the test could be improved.

test/parallel/test-repl-no-sab.js Outdated Show resolved Hide resolved
@codebytere codebytere force-pushed the fix-sab-crash branch 2 times, most recently from 6e29e56 to 489fa03 Compare August 10, 2021 09:12
@nodejs-github-bot
Copy link
Collaborator

@Trott
Copy link
Member

Trott commented Aug 11, 2021

There's a relevant failure in CI. The test added here fails when invoked with test/tools.py --worker.

@codebytere
Copy link
Member Author

@Trott are you potentially able to replicate locally?

i'm seeing

node on git:fix-sab-crash ❯ tools/test.py --worker test/parallel/test-worker-no-sab

=== release test-worker-no-sab ===
Path: parallel/test-worker-no-sab
Command: out/Release/node --no-harmony-sharedarraybuffer /Users/codebytere/Developer/node/tools/run-worker.js /Users/codebytere/Developer/node/test/parallel/test-worker-no-sab.js
[00:00|% 100|+   0|-   1]: Done

passing when i run locally 🤔

@nodejs-github-bot
Copy link
Collaborator

@Trott
Copy link
Member

Trott commented Sep 2, 2021

@Trott are you potentially able to replicate locally?

i'm seeing

node on git:fix-sab-crash ❯ tools/test.py --worker test/parallel/test-worker-no-sab

=== release test-worker-no-sab ===
Path: parallel/test-worker-no-sab
Command: out/Release/node --no-harmony-sharedarraybuffer /Users/codebytere/Developer/node/tools/run-worker.js /Users/codebytere/Developer/node/test/parallel/test-worker-no-sab.js
[00:00|% 100|+   0|-   1]: Done

passing when i run locally 🤔

@codebytere That's not passing. The 1 would be in the + cell if it was passing, and the 0 would b e in the - cell. (You can see the difference if you run it again without --worker. Or you can try running it with --worker but run ttest/parallel/test-worker-no-s* to see one test pass and one test fail.)

The lack of output, though, is odd....

@Trott
Copy link
Member

Trott commented Sep 2, 2021

The lack of output, though, is odd....

The lack of output is legit. (Maybe we should update tools/run-worker.js to provide output in this situation?)

To replicate without the Python script, run this out/Release/node --no-harmony-sharedarraybuffer /Users/trott/io.js/tools/run-worker.js /Users/trott/io.js/test/parallel/test-worker-no-sab.js. It will return no output, but exit with an error code.

Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with my comments addressed.

Comment on lines +7 to +17
const { isMainThread, Worker } = require('worker_threads');

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

const w = new Worker(__filename);

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

if (!isMainThread) process.exit(2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const { isMainThread, Worker } = require('worker_threads');
// Regression test for https://github.com/nodejs/node/issues/39717.
const w = new Worker(__filename);
w.on('exit', common.mustCall((status) => {
assert.strictEqual(status, 2);
}));
if (!isMainThread) process.exit(2);
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);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codebytere Are you ok if we commit this suggestion, run tests, check with @BridgeAR if they can then approve the PR,, and hopefully land? Or is there something about this suggestion that would make you reluctant to do that?

@@ -142,6 +142,9 @@ port.on('message', (message) => {
const originalCwd = process.cwd;

process.cwd = function() {
// SharedArrayBuffers can be disabled with --no-harmony-sharedarraybuffer.
if (typeof SharedArrayBuffer === 'undefined') return originalCwd();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine but we could prevent replacing process.cwd in the first place, so that the extra check is not needed when calling process.cwd().

@@ -7,6 +7,10 @@ const bench = common.createBenchmark(main, {
});

function main({ n }) {
if (typeof SharedArrayBuffer === 'undefined') {
throw new Error('SharedArrayBuffers must be enabled to run this benchmark');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main is going to be executed more than once. As such, it's probably best to move the check to the top of the file.

@codebytere
Copy link
Member Author

Closing as superseded by #41023

@codebytere codebytere closed this Sep 13, 2022
@codebytere codebytere deleted the fix-sab-crash branch September 13, 2022 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
repl Issues and PRs related to the REPL subsystem. worker Issues and PRs related to Worker support.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Repl crash when SharedArrayBuffers are disabled
8 participants