# Embind + emscripten_wasm_worker_post_function_* API appears to be unsupported
Opened this issue · 1 comments
Embind + emscripten_wasm_worker_post_function_* API appears to be unsupported
Hi there, for a few days from now I've been trying to use in my project a combination of both emscripten features: Embind + family of Wasm Worker post function routines (emscripten_wasm_worker_post_function_*); however I've observed an unexpected behaviour from JavaScript's perspective when running the binding functions.
Both ESM and CommonJS build fail, however they manifest in a slightly different way.
Environment used
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.8 (70404efec4458b60b953bc8f1529f2fa112cdfd1)
clang version 21.0.0git (https:/github.com/llvm/llvm-project 23e3cbb2e82b62586266116c8ab77ce68e412cf8)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/alvaro/tools/emsdk/upstream/bin
emcc main.cpp -o ./main.js -v -lembind --no-entry -sMODULARIZE=1 -sEXPORT_ES6=1 -sWASM_WORKERS -sENVIRONMENT="node,worker"
/home/alvaro/tools/emsdk/upstream/bin/clang -target wasm32-unknown-emscripten -fignore-exceptions -matomics -mbulk-memory -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --sysroot=/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot -D__EMSCRIPTEN_SHARED_MEMORY__=1 -D__EMSCRIPTEN_WASM_WORKERS__=1 -DEMSCRIPTEN -Xclang -iwithsysroot/include/fakesdl -Xclang -iwithsysroot/include/compat -v -c main.cpp -o /tmp/emscripten_temp_h7d7966_/main_0.o
clang version 21.0.0git (https:/github.com/llvm/llvm-project 23e3cbb2e82b62586266116c8ab77ce68e412cf8)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/alvaro/tools/emsdk/upstream/bin
(in-process)
"/home/alvaro/tools/emsdk/upstream/bin/clang-21" -cc1 -triple wasm32-unknown-emscripten -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -target-feature +atomics -target-feature +bulk-memory -fvisibility=hidden -debugger-tuning=gdb -fdebug-compilation-dir=/home/alvaro/.trash/proxying-with-emscripten -v -fcoverage-compilation-dir=/home/alvaro/.trash/proxying-with-emscripten -resource-dir /home/alvaro/tools/emsdk/upstream/lib/clang/21 -D __EMSCRIPTEN_SHARED_MEMORY__=1 -D __EMSCRIPTEN_WASM_WORKERS__=1 -D EMSCRIPTEN -isysroot /home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot -internal-isystem /home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1 -internal-isystem /home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1 -internal-isystem /home/alvaro/tools/emsdk/upstream/lib/clang/21/include -internal-isystem /home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten -internal-isystem /home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fignore-exceptions -fexceptions -fcolor-diagnostics -iwithsysroot/include/fakesdl -iwithsysroot/include/compat -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o /tmp/emscripten_temp_h7d7966_/main_0.o -x c++ main.cpp
clang -cc1 version 21.0.0git based upon LLVM 21.0.0git default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1"
ignoring nonexistent directory "/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten"
#include "..." search starts here:
#include <...> search starts here:
/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/fakesdl
/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/compat
/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1
/home/alvaro/tools/emsdk/upstream/lib/clang/21/include
/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/include
End of search list.
/home/alvaro/tools/emsdk/upstream/bin/clang --version
/home/alvaro/tools/emsdk/upstream/bin/wasm-ld -o ./main.wasm /tmp/emscripten_temp_h7d7966_/main_0.o -lembind-rtti -L/home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten -L/home/alvaro/tools/emsdk/upstream/emscripten/src/lib /home/alvaro/tools/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/crtbegin.o -lGL-ww-getprocaddr -lal -lhtml5 -lstubs-debug -lnoexit -lc-ww-debug -ldlmalloc-ww-debug -lcompiler_rt-ww -lc++-ww-noexcept -lc++abi-debug-ww-noexcept -lsockets-ww --whole-archive -lwasm_workers-debug --no-whole-archive -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr /tmp/tmp5on8rsj2libemscripten_js_symbols.so --import-memory --shared-memory --strip-debug --export=emscripten_stack_get_end --export=emscripten_stack_get_free --export=emscripten_stack_get_base --export=emscripten_stack_get_current --export=emscripten_stack_init --export=_emscripten_stack_alloc --export=__getTypeName --export=_embind_initialize_bindings --export=__wasm_call_ctors --export=_emscripten_stack_restore --export=_emscripten_wasm_worker_initialize --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush --export-table -z stack-size=65536 --no-growable-memory --initial-memory=16777216 --no-entry --stack-first --table-base=1
/home/alvaro/tools/emsdk/upstream/bin/llvm-objcopy ./main.wasm ./main.wasm '--remove-section=.debug*' --remove-section=producers --remove-section=name
/home/alvaro/tools/emsdk/node/20.18.0_64bit/bin/node /home/alvaro/tools/emsdk/upstream/emscripten/tools/compiler.mjs -
Or -sEXPORT_ES6=0 in the CommonJS build.
Explanation
Here in my code I have a minimal example to expose the post_job_to_worker function to JavaScript at the same time I consume the wasm_worker.h interfaces.
#include <iostream>
#include <cstdint>
#include <cmath>
#include <emscripten/bind.h>
#include <emscripten/wasm_worker.h>
namespace em = emscripten;
void job()
{
std::cout << "job(): Being of job." << '\n';
std::srand(time(nullptr));
for (std::uint64_t i = 0; i < 1e6; i++)
std::pow(i, static_cast<double>(std::rand()) / RAND_MAX);
std::cout << "job(): End of job." << '\n';
}
void post_job_to_worker()
{
emscripten_wasm_worker_t worker = emscripten_malloc_wasm_worker(/* stackSize: */ 1024);
emscripten_wasm_worker_post_function_v(worker, job);
std::cout << "post_job_to_worker(): Post is done." << '\n';
}
EMSCRIPTEN_BINDINGS(main)
{
em::function("post_job_to_worker", &post_job_to_worker);
}// CommonJS / ESM
// const loadModule = require("./main.js");
import loadModule from "./main.js"
class BackendError extends Error { }
function handleModuleFn(callback) {
try {
callback();
} catch (error) {
throw new BackendError(`${error.message || String(error)}`);
}
}
function wrapModuleFn(Module, fnName) {
if (typeof Module[fnName] != "function")
throw new Error("Not a function.");
return () => handleModuleFn(Module[fnName]);
}
loadModule().then(Module => {
const post_job_to_worker = wrapModuleFn(Module, "post_job_to_worker");
post_job_to_worker();
}).catch(error => console.error(`${error.message || String(error)}`));ESM
When I compile and run the ESM version I get the following error back:
post_job_to_worker(): Post is done.
node:internal/event_target:1094
process.nextTick(() => { throw err; });
^
ReferenceError [Error]: onmessage is not defined
at file:///home/alvaro/.trash/proxying-with-emscripten/main.js:537:11
Emitted 'error' event on Worker instance at:
at [kOnErrorMessage] (node:internal/worker:326:10)
at [kOnMessage] (node:internal/worker:337:37)
at MessagePort.<anonymous> (node:internal/worker:232:57)
at [nodejs.internal.kHybridDispatch] (node:internal/event_target:820:20)
at MessagePort.<anonymous> (node:internal/per_context/messageport:23:28)
Node.js v20.18.0
CommonJS
In the other hand, when I compile to CommonJS and run, the program eventually becomes deadlock.
post_job_to_worker(): Post is done.
💤
After a bit of research, I didn't find any example using the Wasm Workers API and Embind at the same time (examples uses a main function as entry point) which makes me think that maybe this is still considered unsupported.
Could we consider this as a bug ?
Thanks.
After a bit of research, I didn't find any example using the Wasm Workers API and Embind at the same time (examples uses a main function as entry point)
test_embind_wasm_workers should test both? But it is possible you found a specific bug here.