Skip to content

Commit

Permalink
worker: move JoinThread() back into exit callback
Browse files Browse the repository at this point in the history
de2c68c moved this call to
the destructor, under the assumption that that would essentially
be equivalent to running it as part of the callback since the
worker would be destroyed along with the callback.

However, the actual code in
`Environment::RunAndClearNativeImmediates()` comes with the subtlety
that testing whether a JS exception has been thrown
happens between the invocation of the callback and its destruction,
leaving a possible exception from `JoinThread()` potentially
unhandled (and unintentionally silenced through the `TryCatch`).

This affected exceptions thrown from the `'exit'` event of the
Worker, and made the `parallel/test-worker-message-type-unknown`
test flaky, as the invalid message was sometimes only received
during the Worker thread’s exit handler.

Fix this by moving the `JoinThread()` call back to where it was
before.

Refs: #31386

PR-URL: #31468
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
  • Loading branch information
addaleax committed Jan 23, 2020
1 parent 8fb5fe2 commit 1046816
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 2 deletions.
3 changes: 1 addition & 2 deletions src/node_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,6 @@ void Worker::JoinThread() {
}

Worker::~Worker() {
JoinThread();

Mutex::ScopedLock lock(mutex_);

CHECK(stopped_);
Expand Down Expand Up @@ -599,6 +597,7 @@ void Worker::StartThread(const FunctionCallbackInfo<Value>& args) {
[w = std::unique_ptr<Worker>(w)](Environment* env) {
if (w->has_ref_)
env->add_refs(-1);
w->JoinThread();
// implicitly delete w
});
}, static_cast<void*>(w)), 0);
Expand Down
8 changes: 8 additions & 0 deletions test/parallel/test-worker-exit-event-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';
const common = require('../common');
const { Worker } = require('worker_threads');

process.on('uncaughtException', common.mustCall());

new Worker('', { eval: true })
.on('exit', common.mustCall(() => { throw new Error('foo'); }));

0 comments on commit 1046816

Please sign in to comment.