[Haskell-cafe] ANNOUNCE: iterIO-0.1 - iteratee-based IO with pipe operators

Simon Marlow marlowsd at gmail.com
Wed May 11 14:02:21 CEST 2011

On 06/05/2011 16:56, dm-list-haskell-cafe at scs.stanford.edu wrote:
> At Fri, 6 May 2011 10:15:50 +0200,
> Gregory Collins wrote:
>> Hi David,
>> Re: this comment from catchI:
>>> It is not possible to catch asynchronous exceptions, such as
>>> lazily evaluated divide-by-zero errors, the throw function, or
>>> exceptions raised by other threads using throwTo if those
>>> exceptions might arrive anywhere outside of a liftIO call.
>> It might be worth investigating providing a version which can catch
>> asynchronous exceptions if the underlying monad supports it (via
>> MonadCatchIO or something similar). One of the most interesting
>> advantages I can see for IterIO over the other iteratee
>> implementations is that you actually have some control over resource
>> usage -- not being able to catch asynchronous exceptions nullifies
>> much of that advantage. A clear use case for this is timeouts on
>> server threads, where you typically throw a TimeoutException exception
>> to the handling thread using "throwTo" if the timeout is exceeded.
> Excellent point.  There's actually a chance that iterIO already
> catches those kinds of exceptions, but I wasn't sure enough about how
> the Haskell runtime works to make that claim.  I've noticed in
> practice that asynchronous exceptions tend to come exactly when I
> execute the IO>>= operation.  If that's true, then since each IO>>=
> is wrapped in a try block, the exceptions will all be caught (well,
> not divide by zero, but things like throwTo, which I think are more
> important).
> One way I was thinking of implementing this was wrapping the whole
> execution in block, and then calling unblock (unless iterIO's own
> hypothetical block function is called) for every invocation of liftIO.
> Unfortunately, the block and unblock functions now seem to be
> deprecated, and the replacement mask/unmask ones would not be as
> amenable to this technique.
> However, if there's some simpler way to guarantee that>>= is the
> point where exceptions are thrown (and might be the case for GHC in
> practice), then I basically only need to update the docs.  If someone
> with more GHC understanding could explain how asynchronous exceptions
> work, I'd love to hear it...

There's no guarantee of the form that you mention - asynchronous 
exceptions can occur anywhere.  However, there might be a way to do what 
you want (disclaimer: I haven't looked at the implementation of iterIO).

Control.Exception will have a new operation in 7.2.1:

   allowInterrupt :: IO ()
   allowInterrupt = unsafeUnmask $ return ()

which allows an asynchronous exception to be thrown inside mask (until 
7.2.1 you can define it yourself, unsafeUnmask comes from GHC.IO).

As I like saying, mask switches from fully asynchronous mode to polling 
mode, and allowInterrupt is the way you poll.


More information about the Haskell-Cafe mailing list