[Haskell-cafe] ANN: asynchronous-exceptions

João Cristóvão jmacristovao at gmail.com
Thu Feb 6 12:12:29 UTC 2014

Thanks Roman and Michael for the latest clarifications:

I had indeed forgot the case where a thread runned in catchAny spawn
child threads that kill their parent.

> But given how overloaded the term is, I'd be in favor of coming up with a new term to represent what these catch functions are intended to do.

The word currently in my head is 'inner', although Roman's suggestion
of 'enclosed' looks fine too. Internal is also correct, but as it is
regularly used to denote a package internal functions, it may lead to

What these functions (classy prelude/my library spin-off) do is run a
computation, isolating it from the calling thread (through async) and
catching all inner exceptions (of either synchronous or asynchronous
type, raised by either throwIO or throwTo instructions _present
somewhere inside that computation_, or by the RTS but once again
affecting only that computation, not the calling one.

The calling one is thus 'free' to receive asynchronous exceptions in
the meantime (the execution of the inner computation).

Thus, I propose either:

Control.Exception.Inner / Control.Exception.Enclosed

And/or, possibly also rename the functions to something like:

catchAnyInner / catchAnyEnclosed

Although I do not like this last option so much, the function name
gets too long, but that's a personal preference.

What do you think?

2014-02-06 Michael Snoyman <michael at snoyman.com>:
> On Thu, Feb 6, 2014 at 8:17 AM, Roman Cheplyaka <roma at ro-che.info> wrote:
>> > Am I getting this right?
>> Not quite.
>> The enclosed computation may get asynchronous exceptions whatever
>> definition of 'asynchronous' you use -- the exact one (by throw method)
>> or the approximate one (by type).
>> Just a couple of examples:
>> * The thread may catch an async exception from the RTS (such as
>>   BlockedIndefinitelyOnMVar or StackOverflow)
>> * The thread may spawn other threads, passing its pid to them, and one
>>   of its children may eventually kill it
>> So I'd say this method allows to catch any exceptions "related" to
>> the computation, synchronous or asynchronous. It is this "relatedness"
>> that is enforced by running it in a separate thread.
>> Roman
> I definitely think this is important to get our terminology right. A lot of
> the scariness of async exceptions likely spawns from the fact that we use
> the same term to refer to a number of very different cases. Let me give a
> crack at breaking down exceptions:
> * An exception with a synchronous type (e.g., IOException) thrown via
> throwIO. This is the most synchronous of synchronous exceptions.
> * An exception with an asynchronous type (e.g., UserInterrupt) thrown via
> throwIO. There's legitimate room for debate as to what we should call this.
> For my purposes, I'd want to call it a synchronous exception.
> * An exception with a synchronous type thrown via throwTo. Similar to
> previous bullet, but I'd consider this asynchronous.
> * An exception with an asynchronous type thrown via throwTo. This is solidly
> an asynchronous exception.
> Then we have some more interesting questions:
> * What *is* an asynchronous type? By including BlockedIndefinitelyOnMVar, it
> seems like you're defining it to include any exception generated by the RTS.
> However, I'd consider it a synchronous exception: it is generated in direct
> consequence of performing an IO action. It just happens to be generated by
> the RTS instead of via some library talking to the filesystem.
> * What happens if an async exception is caught and then rethrown? Has it
> transformed itself into a synchronous exception? That's a tricky question,
> and likely depends on the exact manner in which is was caught.
> * What happens if a function utilizes some form of asynchronous exception
> mechanism to affect its behavior? The prime example of this is `timeout`, or
> better, the `asyncTimeout` function I displayed above. Internally to that
> function, I think that's an async exception. However, for a *caller* of that
> function, the behavior is actually synchronous: there was no notification
> from the outside world changing the behavior of this function, it simply has
> the possibility to terminate by throwing a Timeout, the same way a function
> may terminate by throwing an IOException.
> That last bullet is crucial to the question of whether classy-prelude's and
> João's catching functions are asynchronous or not. But given how overloaded
> the term is, I'd be in favor of coming up with a new term to represent what
> these catch functions are intended to do.
> Michael

More information about the Haskell-Cafe mailing list