[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.
Cheers,
Simon
More information about the Haskell-Cafe
mailing list