On Fri, Sep 12, 2025 at 8:03 AM John Dallman <jgdatsiem...@gmail.com> wrote:
> > OK, what I want to do isn't possible in Emscripten. > > It looks like it is, actually, but it's a bit complicated. Here's the > scheme: am I requiring anything that doesn't exist? > > I have a great big math library that I want to make available in > WebAssembly form, as a commercial product. It is written in C and C++, and > runs on Android, iOS, Linux, macOS and Windows. Its heritage is from 1980s > and 1990s technical computing, but it is still going strong as a commercial > product. The immediate customers for it want to call it from C/C++ code > that they already use on other platforms (mostly Linux and Windows), rather > than from JavaScript. > > This math library has a test harness, also written in C and C++. The test > cases are *not* written in C/C++, but in interpreted LISP, because that's > quite suitable for handling the data that the library works with, plus it > was easy to write our own portable implementation of the language. > > When you run the test harness, it looks for a LISP file to run and starts > interpreting it, which usually starts by reading a lot more LISP files to > set up a working environment. It then starts reading test scripts and > making the calls to the math library that they request. The test harness > does not exit until it has finished running everything it was given, or it > hits an unrecoverable error. On its existing platforms, it can recover from > SIGSEGV, SIGPFE, and other run-time errors, aborting the test that caused > them and continuing with the subsequent test(s). > > That last part is the problem with a naive WebAssembly implementation, > where the library and the test harness are statically linked together. That > means there's no opportunity for a JavaScript error handler to get involved > before exceptions caused by access violations come flying out of the top of > the test harness. By then, the call stack is gone, and there's no way to > recover from the exception and continue with the next test. > > That's where I'd got to when I wrote " . . . what I want to do isn't > possible in Emscripten." I've had what seem like better ideas since then. > > WebAssembly "modules" are, as far as I understand, kind of like Windows > DLLs or Linux shared libraries. There's a difference in that you can't link > a module against other modules: inter-module calls have to go via > JavaScript. Is that correct? > > I was slow to realise that I can put JavaScript error handlers into any > JavaScript layer. To take advantage of that, I would link my math library > as a module, and its test harness as the main program. The test harness > would call JavaScript code, which would call the library from within a > try/catch block, catch exceptions, call the library's "tidy up" functions, > and return an error code to the test harness. That lets the test harness > recover from exceptions and move on to the next test. It also means I need > to create a JavaScript wrapper for the whole of the library's API, which is > a bit of a big job, but makes the library more generally usable in > WebAssembly code. > > While writing this mail,I realised a possible short-cut to let me get the > test harness running more quickly, without having to generate a wrapper for > hundreds of different functions, with thousands of associated data types > and constants. It goes like this: > > The calls to the library from the test harness are generated by C macros, > and I can add code to those for the WebAssembly build. So it appears I > could use EM_ASM() to create JavaScript error handlers at each of those > call sites, as part of the test harness source. I could then statically > link the library and the test harness for running tests. Is that plausible? > Yes, there is nothing stopping you wrapping your function calls in JS try/catch using EM_ASM or EM_JS. Thanks was what I was trying to show up thread in my EM_ASM example. You don't need to do any kind of dynamic linking to make this work. You could write a C function such as `void* call_with_catch_handler(my_c_function, my_catch_handler_caller)` function and use EM_JS/EM_ASM to implement this. Any fatal errors could then be piped to your `my_catch_handler_caller` function. Is it safe to re-enter a Wasm module after a runtime trap? I'm not sure if the spec specifies this but I think it should work for this kind of use case. > > Thanks in advance, > > John > > > > > On Thu, Sep 11, 2025 at 3:00 PM John Dallman <jgdatsiem...@gmail.com> > wrote: > >> OK, what I want to do isn't possible in Emscripten. >> >> Thanks, everyone. >> >> John >> >> On Tue, Sep 9, 2025 at 7:37 AM Heejin Ahn <ahee...@gmail.com> wrote: >> >>> Correct. Both Emscripten and Wasm SjLj handling requires the setjmp >>> point to be "lower" than the longjmp point, because both use exceptions to >>> simulate setjmp-longjmp. >>> So this works: >>> ``` >>> static jmp_buf buf; >>> >>> void bar() { >>> } >>> >>> int main() { >>> int jmpval = setjmp(buf); >>> if (jmpval == 0) { >>> printf("first call\n"); >>> } else { >>> printf("second call\n"); >>> exit(0); >>> } >>> bar(); >>> return 0; >>> } >>> ``` >>> >>> But this does NOT work: >>> ``` >>> static jmp_buf buf; >>> >>> void foo() { >>> int jmpval = setjmp(buf); >>> if (jmpval == 0) { >>> printf("first call\n"); >>> } else { >>> printf("second call\n"); >>> exit(0); >>> } >>> } >>> >>> void bar() { >>> longjmp(buf, 1); >>> } >>> >>> int main() { >>> foo(); >>> bar(); >>> return 0; >>> } >>> ``` >>> >>> Because by the time longjmp is called, foo's call stack has been >>> destroyed. >>> >>> On Mon, Sep 8, 2025 at 4:31 PM 'Sam Clegg' via emscripten-discuss < >>> emscripten-discuss@googlegroups.com> wrote: >>> >>>> If you want to use `longjmp` in emscripten to get back to start of the >>>> failing test, we have two setjmp/longjmp mechanism. (1) The old emscripten >>>> method (2) The method using wasm exception handling. >>>> >>>> However, I believe that in both cases the target of the long jump has >>>> to be above the caller on the stack. That is, once you unwind the stack >>>> all of the way it will no longer be possible to `longjmp` to the target in >>>> question since its no longer on the stack. @Heejin Ahn >>>> <ahee...@google.com> can you confirm this? >>>> >>>> If that is correct then you will need to some kind of alternative >>>> mechanism when running in emscrpten. Something like this maybe: >>>> >>>> ``` >>>> void run_death_test(death_test_fn_t fn) { >>>> #ifdef __EMSCRIPTEN__ >>>> EM_ASM({ >>>> try { >>>> ...call_fn_from_js.. >>>> report_failure_to_die() >>>> } catch (e) { >>>> report_success_if_e_looks_good(e) >>>> } >>>> }) >>>> #else >>>> setup_longjmp_target(): >>>> fn(); >>>> #endif >>>> } >>>> ``` >>>> >>>> On Mon, Sep 8, 2025 at 4:17 PM Sam Clegg <s...@google.com> wrote: >>>> >>>>> >>>>> >>>>> On Mon, Sep 8, 2025 at 3:40 AM John Dallman <jgdatsiem...@gmail.com> >>>>> wrote: >>>>> >>>>>> > Is the test harness and the library-under-test designed to be >>>>>> compiled into the >>>>>> > same executable? >>>>>> >>>>>> Yes. We prefer to have the library-under-test be a shared object or >>>>>> Windows DLL, on platforms where that's possible, but we can have the >>>>>> harness and the library linked together, and that's what I'm planning to >>>>>> do >>>>>> for WebAssembly. I'm trying to avoid producing a JS wrapper for an API >>>>>> with >>>>>> hundreds of functions, hundreds of structs, and thousands of constants. >>>>>> It >>>>>> also passes lots of pointers to code and data through the interface. My >>>>>> customers who want a WebAssembly version of the library already have >>>>>> C/C++ >>>>>> or Swift code that calls it and want to use it that way. >>>>>> >>>>>> > i.e. on other platforms does it somehow catch and recover from >>>>>> sefaults? >>>>>> >>>>>> Yes.On platforms with signals, those are turned on for segmentation >>>>>> faults (and for some other signals, depending on the platform). The code >>>>>> is >>>>>> C, which sets regular checkpoints with setjmp() and the signal handling >>>>>> function longjmp()s to the latest checkpoint with a "test aborted" value. >>>>>> That's the basic idea, though it's rather more complicated in practice. >>>>>> >>>>> >>>>> Oh wow, `longjmp` out of your signal handler sounds pretty gnarly. >>>>> It's going to be even more gnarly trying to make that work with >>>>> emscripten-generated code, but maybe not impossible? >>>>> >>>>> Are there segfault tests limited in number? i.e. would it be possible >>>>> to choose a different approach when running on the web (just for these few >>>>> tests)? >>>>> >>>>>> >>>>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "emscripten-discuss" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to emscripten-discuss+unsubscr...@googlegroups.com. >>>> To view this discussion visit >>>> https://groups.google.com/d/msgid/emscripten-discuss/CAL_va29WgYahkgoafxhXGs%2BPhfpP-o6GzQSgaTA3xRGhdPKRNg%40mail.gmail.com >>>> <https://groups.google.com/d/msgid/emscripten-discuss/CAL_va29WgYahkgoafxhXGs%2BPhfpP-o6GzQSgaTA3xRGhdPKRNg%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "emscripten-discuss" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to emscripten-discuss+unsubscr...@googlegroups.com. >>> To view this discussion visit >>> https://groups.google.com/d/msgid/emscripten-discuss/CALJpS1Nzcxx0mzS%2BxHTxrETvyGiuppeOcz68PNdjwNtYaG0YcA%40mail.gmail.com >>> <https://groups.google.com/d/msgid/emscripten-discuss/CALJpS1Nzcxx0mzS%2BxHTxrETvyGiuppeOcz68PNdjwNtYaG0YcA%40mail.gmail.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > You received this message because you are subscribed to the Google Groups > "emscripten-discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to emscripten-discuss+unsubscr...@googlegroups.com. > To view this discussion visit > https://groups.google.com/d/msgid/emscripten-discuss/CAH1xqgkCUd%2B6mZjOVBR_AgYdPo%2Be490Oc3Ry00aWP0oVhWh%3DFQ%40mail.gmail.com > <https://groups.google.com/d/msgid/emscripten-discuss/CAH1xqgkCUd%2B6mZjOVBR_AgYdPo%2Be490Oc3Ry00aWP0oVhWh%3DFQ%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/emscripten-discuss/CAL_va293zmaOT35XwQ6pM-Qed2ygWf_Q5SehWK0kJG2eBu9_Aw%40mail.gmail.com.