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.

Reply via email to