re-throwing an asynchronous exception throws it synchronously
If you catch and re-throw an asynchronous exception, the second time it will be thrown synchronously. This only makes a difference when using
unsafeInterleaveIO, because otherwise the
catch will not be inside any thunks.
This could have the unfortunate effect of updating an
unsafePerformIO thunk with
KillThread, or some other asychronous exception that should not be recorded as the value of the thunk.
We believe that exceptions thrown by an exception handler should be thrown in the same mode (synchronous or asynchronous) as the original exception. This means that we need to
keep track of the current exception-throwing mode
push a frame when in an exception handler (we already do this, because the
exception handler is implicitly wrapped in
respect this mode when throwing exceptions.
This raises another issue: catching an exception and recovering by tail-calling out of the exception handler is not a good thing to do. Currently it has the undesirable effect that the thread remains in
block mode, and an explicit
unblock is required. With the changes above, the thread may also remain in "asynchronous exception" mode.
The right way to solve this is just "don't do that". Here's how to use the exception API:
- For cleanup, use
- To modify the exception, use
- For recovery, use
Perhaps we should be deprecating
catch? Or perhaps
catch should be implemented in terms of
try, so it doesn't have the implicit
block / re-throw async exceptions behaviour?