Skip to content
3 changes: 3 additions & 0 deletions src/closure-externs/node-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,6 @@ Buffer.prototype.slice = function(start, end) {};
* @nosideeffects
*/
Buffer.prototype.toString = function(encoding, start, end) {};

Worker.prototype.ref = function() {};
Worker.prototype.unref = function() {};
29 changes: 26 additions & 3 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ var LibraryPThread = {
// worker pool as an unused worker.
worker.pthread_ptr = 0;

#if ENVIRONMENT_MAY_BE_NODE
if (ENVIRONMENT_IS_NODE) {
// Once a pthread has finished and the worker becomes idle, mark it
// as weakly referenced so that its existence does not prevent Node.js
// from exiting.
worker.unref();
}
#endif

// Finally, free the underlying (and now-unused) pthread structure in
// linear memory.
__emscripten_thread_free_data(pthread_ptr);
Expand Down Expand Up @@ -267,11 +276,18 @@ var LibraryPThread = {
cancelThread(d['thread']);
} else if (cmd === 'loaded') {
worker.loaded = true;
#if ENVIRONMENT_MAY_BE_NODE
if (ENVIRONMENT_IS_NODE) {
// Once worker is loaded & idle, mark it as weakly referenced,
// so that mere existence of a Worker in the pool does not prevent
// Node.js from exiting the app.
worker.unref();
}
#endif
if (onFinishedLoading) onFinishedLoading(worker);
// If this Worker is already pending to start running a thread, launch the thread now
if (worker.runPthread) {
worker.runPthread();
delete worker.runPthread;
}
} else if (cmd === 'print') {
out('Thread ' + d['threadId'] + ': ' + d['text']);
Expand Down Expand Up @@ -584,12 +600,19 @@ var LibraryPThread = {
#endif
worker.runPthread = () => {
// Ask the worker to start executing its pthread entry point function.
#if ENVIRONMENT_MAY_BE_NODE
if (ENVIRONMENT_IS_NODE) {
// Mark worker as strongly referenced once we start executing a pthread,
// so that Node.js doesn't exit while the pthread is running.
worker.ref();
}
#endif
msg.time = performance.now();
worker.postMessage(msg, threadParams.transferList);
delete worker.runPthread;
};
if (worker.loaded) {
worker.runPthread();
delete worker.runPthread;
}
return 0;
},
Expand Down Expand Up @@ -671,7 +694,7 @@ var LibraryPThread = {

var offscreenCanvases = {}; // Dictionary of OffscreenCanvas objects we'll transfer to the created thread to own
var moduleCanvasId = Module['canvas'] ? Module['canvas'].id : '';
// Note that transferredCanvasNames might be null (so we cannot do a for-of loop).
// Note that transferredCanvasNames might be null (so we cannot do a for-of loop).
for (var i in transferredCanvasNames) {
var name = transferredCanvasNames[i].trim();
var offscreenCanvasInfo;
Expand Down
18 changes: 0 additions & 18 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2766,7 +2766,6 @@ def test_pthread_proxying_cpp(self):

@node_pthreads
def test_pthread_proxying_dropped_work(self):
self.set_setting('EXIT_RUNTIME')
self.set_setting('PTHREAD_POOL_SIZE=2')
self.do_run_in_out_file_test('pthread/test_pthread_proxying_dropped_work.c')

Expand All @@ -2779,7 +2778,6 @@ def test_pthread_proxying_refcount(self):

@node_pthreads
def test_pthread_dispatch_after_exit(self):
self.set_setting('EXIT_RUNTIME')
self.do_run_in_out_file_test('pthread/test_pthread_dispatch_after_exit.c', interleaved_output=False)

@node_pthreads
Expand All @@ -2791,7 +2789,6 @@ def test_pthread_atexit(self):

@node_pthreads
def test_pthread_nested_work_queue(self):
self.set_setting('EXIT_RUNTIME')
self.set_setting('PTHREAD_POOL_SIZE', 1)
self.do_run_in_out_file_test('pthread/test_pthread_nested_work_queue.c')

Expand All @@ -2804,13 +2801,11 @@ def test_pthread_thread_local_storage(self):

@node_pthreads
def test_pthread_cleanup(self):
self.set_setting('EXIT_RUNTIME')
self.set_setting('PTHREAD_POOL_SIZE', 4)
self.do_run_in_out_file_test('pthread/test_pthread_cleanup.cpp')

@node_pthreads
def test_pthread_setspecific_mainthread(self):
self.set_setting('EXIT_RUNTIME')
print('.. return')
self.do_runf(test_file('pthread/test_pthread_setspecific_mainthread.c'), 'done!', emcc_args=['-DRETURN'])
print('.. exit')
Expand All @@ -2820,7 +2815,6 @@ def test_pthread_setspecific_mainthread(self):

@node_pthreads
def test_pthread_attr_getstack(self):
self.set_setting('EXIT_RUNTIME')
self.set_setting('PTHREAD_POOL_SIZE', 1)
self.do_run_in_out_file_test('pthread/test_pthread_attr_getstack.c')

Expand All @@ -2836,7 +2830,6 @@ def test_pthread_abort(self):

@node_pthreads
def test_pthread_abort_interrupt(self):
self.set_setting('EXIT_RUNTIME')
self.set_setting('PTHREAD_POOL_SIZE', 1)
expected = ['Aborted(). Build with -sASSERTIONS for more info', 'Aborted(native code called abort())']
self.do_runf(test_file('pthread/test_pthread_abort_interrupt.c'), expected, assert_returncode=NON_ZERO)
Expand Down Expand Up @@ -9112,13 +9105,11 @@ def test_pthread_c11_threads(self):
@node_pthreads
def test_pthread_cxx_threads(self):
self.set_setting('PTHREAD_POOL_SIZE', 1)
self.set_setting('EXIT_RUNTIME')
self.do_run_in_out_file_test('pthread/test_pthread_cxx_threads.cpp')

@node_pthreads
def test_pthread_busy_wait(self):
self.set_setting('PTHREAD_POOL_SIZE', 1)
self.set_setting('EXIT_RUNTIME')
self.do_run_in_out_file_test('pthread/test_pthread_busy_wait.cpp')

@node_pthreads
Expand Down Expand Up @@ -9167,11 +9158,9 @@ def test_pthread_exit_process(self):

@node_pthreads
def test_pthread_exit_main(self):
self.set_setting('EXIT_RUNTIME')
self.do_run_in_out_file_test('core/pthread/test_pthread_exit_main.c')

def test_pthread_exit_main_stub(self):
self.set_setting('EXIT_RUNTIME')
self.do_run_in_out_file_test('core/pthread/test_pthread_exit_main.c')

@node_pthreads
Expand Down Expand Up @@ -9223,7 +9212,6 @@ def test_emscripten_futexes(self):
@node_pthreads
def test_stdio_locking(self):
self.set_setting('PTHREAD_POOL_SIZE', '2')
self.set_setting('EXIT_RUNTIME')
self.do_run_in_out_file_test('core/test_stdio_locking.c')

@needs_dylink
Expand All @@ -9238,7 +9226,6 @@ def test_pthread_dylink_basics(self):
@node_pthreads
def test_pthread_dylink(self):
self.emcc_args.append('-Wno-experimental')
self.set_setting('EXIT_RUNTIME')
self.set_setting('USE_PTHREADS')
self.set_setting('PTHREAD_POOL_SIZE', 2)
main = test_file('core/pthread/test_pthread_dylink.c')
Expand All @@ -9259,7 +9246,6 @@ def test_pthread_dylink(self):
@node_pthreads
def test_pthread_dylink_entry_point(self, args):
self.emcc_args.append('-Wno-experimental')
self.set_setting('EXIT_RUNTIME')
self.set_setting('USE_PTHREADS')
self.set_setting('PTHREAD_POOL_SIZE', 1)
main = test_file('core/pthread/test_pthread_dylink_entry_point.c')
Expand All @@ -9269,7 +9255,6 @@ def test_pthread_dylink_entry_point(self, args):
@node_pthreads
def test_pthread_dylink_exceptions(self):
self.emcc_args.append('-Wno-experimental')
self.set_setting('EXIT_RUNTIME')
self.set_setting('USE_PTHREADS')
self.emcc_args.append('-fexceptions')
self.dylink_testf(test_file('core/pthread/test_pthread_dylink_exceptions.cpp'))
Expand Down Expand Up @@ -9312,7 +9297,6 @@ def test_pthread_dlsym(self):
@node_pthreads
def test_pthread_dylink_tls(self):
self.emcc_args.append('-Wno-experimental')
self.set_setting('EXIT_RUNTIME')
self.set_setting('USE_PTHREADS')
self.set_setting('PTHREAD_POOL_SIZE', 1)
main = test_file('core/pthread/test_pthread_dylink_tls.c')
Expand All @@ -9322,7 +9306,6 @@ def test_pthread_dylink_tls(self):
@node_pthreads
def test_pthread_dylink_longjmp(self):
self.emcc_args.append('-Wno-experimental')
self.set_setting('EXIT_RUNTIME')
self.set_setting('USE_PTHREADS')
self.set_setting('PTHREAD_POOL_SIZE=1')
main = test_file('core/pthread/test_pthread_dylink_longjmp.c')
Expand All @@ -9332,7 +9315,6 @@ def test_pthread_dylink_longjmp(self):
@node_pthreads
def test_pthread_dylink_main_module_1(self):
self.emcc_args.append('-Wno-experimental')
self.set_setting('EXIT_RUNTIME')
self.set_setting('USE_PTHREADS')
self.set_setting('MAIN_MODULE')
self.do_runf(test_file('hello_world.c'))
Expand Down
1 change: 0 additions & 1 deletion test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -9101,7 +9101,6 @@ def test_node_js_pthread_module(self):
const test_module = require("./module");
test_module().then((test_module_instance) => {
test_module_instance._main();
process.exit(0);
});
'''
ensure_dir('subdir')
Expand Down