Emscripten: Custom message handler when using pthreads

Viewed 239

TL;DR
How do I add a message handler to Emscripten's generated worker output?


I am porting my C++ terminal application to WASM using Emscripten so I can run it in a browser. The application is blocking and uses a thread internally, so I build with PROXY_TO_PTHREAD and USE_PTHREADS which results in a web-worker being launched to run main and another for the application thread (this is how Emscripten emulates pthreads in the browser).

The application can require input data, and for that I need to get text from a HTML element into my worker to feed the application's stdin. Using the Worker API I can use postMessage to send data to my worker, but I can't figure out how to add a message handler in the worker!

There is a Module.onCustomMessage property which can do this, but it is only valid when built with PROXY_TO_WORKER - which isn't allowed when using pthreads.

Another approach I tried, which is very hacky, is to try to wrap the onmessage function in the worker:

EM_JS(int, malbolge_input, (char* buffer, int maxlen), {
    return Asyncify.handleAsync(async () => {
        if (typeof Module.malbolgeConfigured == "undefined") {
            ...

            let standard_handlers = self.onmessage;
            self.onmessage = function(e) {
                console.log("\tWorker handler: " + e.data.cmd);

                if (e.data.cmd === "input_text") {
                    Module.malbolgeInputQueue.push(e.data.input_text);
                    Module.malbolgeInputNotify();
                } else {
                    standard_handlers(e);
                }
            };
        }
    ...

Unfortunately only the original function is ever called, never the wrapper, and I don't know why.

Another alternative is to patch the generated *_worker.js to manually add a handler, but it is a very brittle solution as it will be very dependent on the version of Emscripten being used.

0 Answers
Related