
Asynchronous Exceptions in Practice - dmit
https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html
======
runeks
> The Haskell runtime keeps track of how much memory each Haskell thread has
> allocated in total, and if that total exceeds the limit we set, the thread
> receives an asynchronous exception, namely AllocationLimitExceeded. The user
> code running on our platform is not permitted to catch this exception,
> instead the server catches it, logs some data to aid debugging, and sends an
> error back to the client that initiated the request.

This is actually pretty cool. This way the server stays in charge of the
threads it spawns, rather than having to build in some auto-destruct feature
into the thread itself (which may not necessarily fire). The thread becomes
more like a sandboxed environment -- with resource quotas -- than an
independent entity, which I think is what we want, if we want to be able to
reason about our code.

------
rkrzr
"You can throw an exception to another thread, at any time;" "The other thread
will receive the exception immediately, whatever it is doing."

Does anybody know how this is implemented in the runtime system? How does one
thread communicate with another thread? And how do you need to look at this
for it _not_ to be a side-effect?

Any insight is much appreciated.

~~~
jwlato
I surely don't know as much as simonmar about this, but I think this is a
rhetorical shortcut. My understanding is that when a Haskell thread receiving
the exception needs to allocate on the heap, the executing context will
instead raise the exception.

As for why it's not a side effect, in Haskell all exceptions are considered to
be bottom, the value that inhabits every type. Thus an exception can be raised
anywhere and have any type. They can only be handled in IO though.

------
danidiaz
A common pattern is trying to recorver from IO exceptions but treating
asynchronous exceptions as fatal. The safe-exceptions package helps with that:
[http://hackage.haskell.org/package/safe-
exceptions](http://hackage.haskell.org/package/safe-exceptions)

------
xamuel
>"When we originally added asynchronous exceptions to Haskell ... was shortly
after Java had removed the equivalent feature, because it was impossible to
program with."

>"...if [Haskell wants] to be able to interrupt ... asynchronous exceptions
are the only way, because polling would be a side-effect"

File under "Indictments against Haskell". We're gonna need a bigger filing
cabinet.

~~~
jerf
The problem with asynchronous exceptions in languages with unconstrained
mutability and effects is that there is no way to guarantee what happens when
you get the asynchronous exception, especially when you get another one while
the handler is running, and maybe another one while that is running, etc. You
can be in the middle of an arbitrary sequence of mutations that you don't
expect to be interrupted, in a critical section protected by any number of
mutexes or whatever, and then the exception arrives when you weren't expecting
it. Then while handling that, another one arrives in the middle of your
handler. It turns out there just isn't a solution to this problem for
languages that don't have constrained mutation.

In Haskell, this turns out to be an occasionally challenging problem rather
than an impossible one. As the article said, it does get tricky near a few of
the seams, but in most code you can just ignore the problem and not worry
about it. Your immutable computation gets interrupted at an arbitrary location
in the middle of it, and you just throw away the pure components of the
computation and run the cleanup code from "bracket"s. (And other runtime
details.)

It's the same reason Haskell has usable STM and languages with unconstrained
effects do not. (Yes, you can download libraries that are STM for a lot of
languages, but they are generally not usable.) In a language with
unconstrained mutation and side effects, you can't reasonably roll back a
transaction because you can't undo the effects, and you can't constrain the
programmer to not use any effects. As it turns out, STM turned out not to be a
silver bullet and it's merely a single tool in Haskell's toolbelt, one that
isn't even necessarily used that often, but because Haskell could implement
it, the Haskell community was able to discover that by using it, rather than
just theorizing about how nice it may or may not be if only we could have an
implementation.

