diff --git a/src/library.js b/src/library.js index 140382f802c8..94ce5806faff 100644 --- a/src/library.js +++ b/src/library.js @@ -3332,11 +3332,7 @@ addToLibrary({ } } #endif -#if MINIMAL_RUNTIME - throw e; -#else quit_(1, e); -#endif }, $runtimeKeepaliveCounter__internal: true, diff --git a/src/library_pthread.js b/src/library_pthread.js index 2966bae0c2db..c57b75148b7d 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js @@ -1101,8 +1101,6 @@ var LibraryPThread = { '_emscripten_thread_exit', #if !MINIMAL_RUNTIME '$keepRuntimeAlive', -#endif -#if EXIT_RUNTIME && !MINIMAL_RUNTIME '$runtimeKeepaliveCounter', #endif ], @@ -1110,7 +1108,7 @@ var LibraryPThread = { #if PTHREADS_DEBUG dbg(`invokeEntryPoint: ${ptrToString(ptr)}`); #endif -#if EXIT_RUNTIME && !MINIMAL_RUNTIME +#if !MINIMAL_RUNTIME // An old thread on this worker may have been canceled without returning the // `runtimeKeepaliveCounter` to zero. Reset it now so the new thread won't // be affected. diff --git a/test/other/test_pthread_reuse.c b/test/other/test_pthread_reuse.c new file mode 100644 index 000000000000..4bb52e1dc311 --- /dev/null +++ b/test/other/test_pthread_reuse.c @@ -0,0 +1,57 @@ +#include +#include +#include + +#include +#include +#include + +_Atomic int ready; + +void markReady(void* arg) { + ready = 1; +} + +void* thread_main(void* arg) { + int keepalive = (intptr_t)arg; + emscripten_outf("in thread_main: %d", keepalive); + if (keepalive) { + // Exit with live runtime. Once we are in the event loop call markReady. + emscripten_async_call(markReady, NULL, 0); + emscripten_exit_with_live_runtime(); + } + return NULL; +} + +void checkThreadPool() { + int running = EM_ASM_INT(return PThread.runningWorkers.length); + int unused = EM_ASM_INT(return PThread.unusedWorkers.length); + printf("running=%d unused=%d\n", running, unused); + assert(running == 0); + assert(unused == 1); +} + +int main() { + printf("in main\n"); + checkThreadPool(); + pthread_t t, t2; + + for (int i = 0; i < 3; i++) { + ready = 0; + + // Create a thread that exit's with a non-zero keepalive counter + pthread_create(&t, NULL, thread_main, (void*)1); + while (!ready) {} + pthread_cancel(t); + pthread_join(t, NULL); + checkThreadPool(); + + // Create a second thread that should re-use the same worker. + // This thread should reset its keepalive counter on startup and + // be able to exit normally. + pthread_create(&t2, NULL, thread_main, NULL); + pthread_join(t2, NULL); + checkThreadPool(); + } + printf("done\n"); +} diff --git a/test/other/test_pthread_reuse.out b/test/other/test_pthread_reuse.out new file mode 100644 index 000000000000..e15e45cee8e2 --- /dev/null +++ b/test/other/test_pthread_reuse.out @@ -0,0 +1,15 @@ +in main +running=0 unused=1 +in thread_main: 1 +running=0 unused=1 +in thread_main: 0 +running=0 unused=1 +in thread_main: 1 +running=0 unused=1 +in thread_main: 0 +running=0 unused=1 +in thread_main: 1 +running=0 unused=1 +in thread_main: 0 +running=0 unused=1 +done diff --git a/test/test_other.py b/test/test_other.py index 38fa0354d630..586957f22555 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -11803,6 +11803,11 @@ def test_pthread_asyncify(self): self.set_setting('EXIT_RUNTIME') self.do_run_in_out_file_test('other/test_pthread_asyncify.c') + @node_pthreads + def test_pthread_reuse(self): + self.set_setting('PTHREAD_POOL_SIZE', 1) + self.do_run_in_out_file_test('other/test_pthread_reuse.c') + def test_stdin_preprocess(self): create_file('temp.h', '#include ') outputStdin = self.run_process([EMCC, '-x', 'c++', '-dM', '-E', '-'], input="#include ", stdout=PIPE).stdout