Stream: git-wasmtime

Topic: wasmtime / Issue #2456 Consider adding support for MacOS ...


view this post on Zulip Wasmtime GitHub notifications bot (Nov 28 2020 at 09:22):

Jake-Shadle opened Issue #2456:

Currently, wasmtime hooks various signals in traphandlers on Unix platforms before executing wasm code so that it can catch and handle various runtime issues without actually crashing the host program. However, on MacOS there is an additional error handling mechanism, Mach Exceptions. By default a Mach exception will be turned into a unix signal, however, if the application binds their own exception port via task_set_exception_ports or similar, it's up to that handler to actual forward to the default signal mechanism, but in most cases they will probably just abort the process instead, even though wasmtime would have successfully recovered program execution in its signal handler.

Feature

The feature I'm proposing would be for wasmtime's traphandler to use exception ports when targeting MacOS (and I guess iOS, but I would assume that target is not relevant for wasmtime due to its code execution rules?), forwarding exceptions to whatever previously registered exception port if the exception is not one of the one's wasmtime wants to handle.

Benefit

The application could have previously registered signal handlers or exception ports on Mac and still function as expected whenever wasmtime executes exceptional wasm code.

Implementation

  1. Store the previous exception port(s)
  2. Set exception port to wasmtime's own handler
  3. When entering trap handling, signal to the handler thread (shared memory, ipc, whatever) that the handler should treat the exceptions it can handle (the equivalents of the SIGILL etc) as runtime errors, but all other exceptions, or when not executing wasm code, should be forwarded to the previous exception port(s)
  4. When exiting trap handling, tell the handler thread to always forward exceptions

Also, one thing that would possibly make this easier would just be to directly signal the thread, similar to Mac's own ux_handler code as seen here.

Alternatives

The alternative would just be to not do this at all, but in that case I think having a warning in the documentation somewhere so that people running wasmtime on a Mac are aware that having task*_set_exception_ports in their program might mean that wasmtime's normal behavior of catching and handling exception wasm code won't even execute depending on how the user exception handler is implemented.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 28 2020 at 09:24):

Jake-Shadle commented on Issue #2456:

Oh and yes, I found this because I added breakpad to our project so we can report crashes effectively, but then someone on mac had a panic in some of their WASM code, so I had to go down this rabbit hole.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 28 2020 at 09:38):

Jake-Shadle edited Issue #2456:

Currently, wasmtime hooks various signals in traphandlers on Unix platforms before executing wasm code so that it can catch and handle various runtime issues without actually crashing the host program. However, on MacOS there is an additional error handling mechanism, Mach Exceptions. By default a Mach exception will be turned into a unix signal, however, if the application binds their own exception port via task_set_exception_ports or similar, it's up to that handler to actual forward to the default signal mechanism, but in most cases they will probably just abort the process instead, even though wasmtime would have successfully recovered program execution in its signal handler.

Feature

The feature I'm proposing would be for wasmtime's traphandler to use exception ports when targeting MacOS (and I guess iOS, but I would assume that target is not relevant for wasmtime due to its code execution rules?), forwarding exceptions to whatever previously registered exception port if the exception is not one of the one's wasmtime wants to handle.

Benefit

The application could have previously registered signal handlers or exception ports on Mac and still function as expected whenever wasmtime executes exceptional wasm code.

Implementation

\* I think basically the implementation is mostly conceptually the same as the current signal handling approach, but basically it would be something like...

  1. Store the previous exception port(s)
  2. Set exception port to wasmtime's own handler
  3. When entering trap handling, signal to the handler thread (shared memory, ipc, whatever) that the handler should treat the exceptions it can handle (the equivalents of the SIGILL etc) as runtime errors, but all other exceptions, or when not executing wasm code, should be forwarded to the previous exception port(s)
  4. When exiting trap handling, tell the handler thread to always forward exceptions

Also, one thing that would possibly make this easier would just be to directly signal the thread, similar to Mac's own ux_handler code as seen here.

\* All of this information is gleaned from Mach Exceptions, Signas, and Breakpad's Exception Handler, as the official Apple documentation is, frankly, garbage.

Alternatives

The alternative would just be to not do this at all, but in that case I think having a warning in the documentation somewhere so that people running wasmtime on a Mac are aware that having task*_set_exception_ports in their program might mean that wasmtime's normal behavior of catching and handling exception wasm code won't even execute depending on how the user exception handler is implemented.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 30 2020 at 15:27):

alexcrichton commented on Issue #2456:

Thanks for the report! This seems like something that might be worthwhile to investigate, but somewhat orthogonally the signal handling in wasmtime should forward signals to the previous signal handler if any is registered. Did you find this to not work, however? If so could you describe a bit more about the bug that's happening with the signal handlers today?

view this post on Zulip Wasmtime GitHub notifications bot (Nov 30 2020 at 15:31):

bjorn3 commented on Issue #2456:

I think what happens is that the exception gets delivered to an exception port registered by the application before the wasmtime signal handler has the chance to run, thus causing all exceptions that should be handled by wasmtime to instead go to the exception port registered by the application.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 30 2020 at 15:31):

bjorn3 edited a comment on Issue #2456:

I think the problem is that the exception gets delivered to an exception port registered by the application before the wasmtime signal handler has the chance to run, thus causing all exceptions that should be handled by wasmtime to instead go to the exception port registered by the application.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 30 2020 at 18:03):

Jake-Shadle commented on Issue #2456:

Yes, exactly what @bjorn3 said, I've worked around this by instead changing our breakpad fork to just not register the exception ports and instead hook all of the signals that the exception handler used to cover, which works nicely since it can seamlessly work with wasmtime, but it seems like having this in wasmtime would make sense so that it's not at the mercy of whatever other exception handler can be registered that doesn't play nicely.

I was actually surprised that breakpad didn't have an option to change this, but I guess having both breakpad alongside a piece of code like wasmtime that depends on handling signals is fairly niche or something.

view this post on Zulip Wasmtime GitHub notifications bot (Nov 30 2020 at 18:50):

fitzgen commented on Issue #2456:

Supporting this makes sense to me. Probably faster too, not that it really matters in this particular case :laughing:

view this post on Zulip Wasmtime GitHub notifications bot (Nov 30 2020 at 22:58):

alexcrichton commented on Issue #2456:

Ah yes thanks for clarifying! Also, yes, agreed we should add this to Wasmtime! Just need to figure out how...

view this post on Zulip Wasmtime GitHub notifications bot (Dec 02 2020 at 19:52):

sunfishcode commented on Issue #2456:

The old SignalHandlers.cpp file removed in #1365 theoretically had code to do this, though the code is in C++; it may help show what needs to be done here.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 03 2020 at 15:35):

alexcrichton commented on Issue #2456:

I was poking around this a bit last night (here's the file in its full glory), and one snag is going to be that the exception handler runs on a separate thread because a different thread receives the mach message. Our determination of whether a wasm trap ocurred, however, requires access to thread-local state (e.g. to read the store's map of registered JIT addresses and see if we collide with any of them). If we're running the handler on a separate thread, though, I'm not sure how the mach exception handling thread will know how to associated a store's JIT data with the exception that it just received.

One possible solution is to have a global map that's updated on entry/exit into wasm, but that would require mutex-like synchronization which could be somewhat expensive too.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 10 2020 at 18:55):

alexcrichton commented on Issue #2456:

Looking at SpiderMonkey, it appears that registers code segments in a process-global map which has synchronized access. I think the answer for wasmtime is likely the same. Somehow we'll need to have cheap-ish "is this a jit region" test and then some way to go from the register state to the thread-local information about the Store and such.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 03 2021 at 21:05):

alexcrichton commented on Issue #2456:

I've got a prototype of this at https://github.com/bytecodealliance/wasmtime/pull/2632 now. @Jake-Shadle if you're still interested mind giving that a spin and seeing if it works for your use case?

view this post on Zulip Wasmtime GitHub notifications bot (Feb 03 2021 at 21:27):

Jake-Shadle commented on Issue #2456:

We'd be happy to try this out, though I probably can't get to it this week, but next week!

view this post on Zulip Wasmtime GitHub notifications bot (Mar 17 2021 at 14:43):

alexcrichton closed Issue #2456:

Currently, wasmtime hooks various signals in traphandlers on Unix platforms before executing wasm code so that it can catch and handle various runtime issues without actually crashing the host program. However, on MacOS there is an additional error handling mechanism, Mach Exceptions. By default a Mach exception will be turned into a unix signal, however, if the application binds their own exception port via task_set_exception_ports or similar, it's up to that handler to actual forward to the default signal mechanism, but in most cases they will probably just abort the process instead, even though wasmtime would have successfully recovered program execution in its signal handler.

Feature

The feature I'm proposing would be for wasmtime's traphandler to use exception ports when targeting MacOS (and I guess iOS, but I would assume that target is not relevant for wasmtime due to its code execution rules?), forwarding exceptions to whatever previously registered exception port if the exception is not one of the one's wasmtime wants to handle.

Benefit

The application could have previously registered signal handlers or exception ports on Mac and still function as expected whenever wasmtime executes exceptional wasm code.

Implementation

\* I think basically the implementation is mostly conceptually the same as the current signal handling approach, but basically it would be something like...

  1. Store the previous exception port(s)
  2. Set exception port to wasmtime's own handler
  3. When entering trap handling, signal to the handler thread (shared memory, ipc, whatever) that the handler should treat the exceptions it can handle (the equivalents of the SIGILL etc) as runtime errors, but all other exceptions, or when not executing wasm code, should be forwarded to the previous exception port(s)
  4. When exiting trap handling, tell the handler thread to always forward exceptions

Also, one thing that would possibly make this easier would just be to directly signal the thread, similar to Mac's own ux_handler code as seen here.

\* All of this information is gleaned from Mach Exceptions, Signas, and Breakpad's Exception Handler, as the official Apple documentation is, frankly, garbage.

Alternatives

The alternative would just be to not do this at all, but in that case I think having a warning in the documentation somewhere so that people running wasmtime on a Mac are aware that having task*_set_exception_ports in their program might mean that wasmtime's normal behavior of catching and handling exception wasm code won't even execute depending on how the user exception handler is implemented.


Last updated: Dec 23 2024 at 12:05 UTC