diff --git a/src/lib/libembind.js b/src/lib/libembind.js index 461dc5a194de1..ee9f4c8ca917b 100644 --- a/src/lib/libembind.js +++ b/src/lib/libembind.js @@ -31,6 +31,10 @@ var LibraryEmbind = { $UnboundTypeError: class extends Error {}, $PureVirtualError: class extends Error {}, $GenericWireTypeSize: {{{ 2 * POINTER_SIZE }}}, +#if PTHREADS || WASM_WORKERS + $postCtors: null, // Unused symbol stub for injecting post ctors call. + $postCtors__postset: () => { addAtPostCtor('__embind_post_ctors()'); }, +#endif #if EMBIND_AOT $InvokerFunctions: '<<< EMBIND_AOT_INVOKERS >>>', #endif @@ -2320,4 +2324,8 @@ var LibraryEmbind = { }, }; +#if PTHREADS || WASM_WORKERS +extraLibraryFuncs.push('$postCtors'); +#endif + addToLibrary(LibraryEmbind); diff --git a/src/lib/libwasm_worker.js b/src/lib/libwasm_worker.js index dbd2d8674cc38..98efa8352cf99 100644 --- a/src/lib/libwasm_worker.js +++ b/src/lib/libwasm_worker.js @@ -138,7 +138,7 @@ addToLibrary({ #if EMBIND // Embind must initialize itself on all threads, as it generates support JS. - __embind_initialize_bindings(); + __embind_initialize_worker_bindings(); #endif #if AUDIO_WORKLET diff --git a/src/runtime_pthread.js b/src/runtime_pthread.js index 6132b4aa9c4af..63223c2eeaff7 100644 --- a/src/runtime_pthread.js +++ b/src/runtime_pthread.js @@ -147,7 +147,7 @@ if (ENVIRONMENT_IS_PTHREAD) { #endif // Embind must initialize itself on all threads, as it generates support JS. // We only do this once per worker since they get reused - __embind_initialize_bindings(); + __embind_initialize_worker_bindings(); #endif // EMBIND initializedJS = true; } diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index 3e1336ef9cfb3..dff4af64435ea 100644 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -19,6 +19,8 @@ using namespace emscripten; using namespace internal; +static std::atomic embind_initialized(false); + extern "C" { const char* __getTypeName(const std::type_info* ti) { @@ -52,7 +54,13 @@ const char* __getTypeName(const std::type_info* ti) { static InitFunc* init_funcs = nullptr; -void _embind_initialize_bindings() { +void _embind_post_ctors() { + embind_initialized = true; + embind_initialized.notify_all(); +} + +void _embind_initialize_worker_bindings() { + embind_initialized.wait(false); for (auto* f = init_funcs; f; f = f->next) { f->init_func(); } diff --git a/test/embind/test_embind_val_in_static_pthread.cpp b/test/embind/test_embind_val_in_static_pthread.cpp new file mode 100644 index 0000000000000..cb51f3f43fa5d --- /dev/null +++ b/test/embind/test_embind_val_in_static_pthread.cpp @@ -0,0 +1,14 @@ +#include +#include +#include + +auto BGThread = std::thread([]() { + auto globalThis = emscripten::val::global("globalThis"); + assert(globalThis.typeOf().as() == "object"); + printf("worker\n"); +}); + +int main() { + BGThread.join(); + printf("done\n"); +} diff --git a/test/test_other.py b/test/test_other.py index 05b13546d5a90..30b1232d45e88 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -3429,6 +3429,12 @@ class MyClass {}; ''') self.do_runf('main.cpp', emcc_args=['-lembind']) + @node_pthreads + def test_embind_val_in_static_pthread(self): + # Test that threads wait for embind to initialize before running. + self.emcc_args += ['-lembind', '-sPTHREAD_POOL_SIZE=2'] + self.do_runf('embind/test_embind_val_in_static_pthread.cpp', 'worker\ndone\n') + @requires_jspi @parameterized({ '': [['-sJSPI_EXPORTS=async*']], diff --git a/tools/link.py b/tools/link.py index 13d53ecd17cff..b4c7cf0a29b74 100644 --- a/tools/link.py +++ b/tools/link.py @@ -1376,7 +1376,7 @@ def limit_incoming_module_api(): # https://github.com/emscripten-core/emscripten/issues/21653 settings.REQUIRED_EXPORTS.append('__getTypeName') if settings.PTHREADS or settings.WASM_WORKERS: - settings.REQUIRED_EXPORTS.append('_embind_initialize_bindings') + settings.REQUIRED_EXPORTS += ['_embind_initialize_worker_bindings', '_embind_post_ctors'] # Needed to assign the embind exports to the ES exports. if settings.MODULARIZE == 'instance': settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$addOnPostCtor'] diff --git a/tools/system_libs.py b/tools/system_libs.py index ded959c84562f..1b19d17fb00db 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -1927,7 +1927,7 @@ class libwebgpu_cpp(MTLibrary): src_files = ['webgpu_cpp.cpp'] -class libembind(Library): +class libembind(MTLibrary): name = 'libembind' never_force = True