[reactive] Re: black hole detection and concurrency

Simon Marlow marlowsd at gmail.com
Tue Jan 6 09:45:41 EST 2009

Isaac Dupree wrote:
> therefore mapException is equally buggy!
>> mapException :: (Exception e1, Exception e2) => (e1 -> e2) -> a -> a
>> mapException f v = unsafePerformIO (catch (evaluate v)
>>                                           (\x -> throw (f x)))
> If it maps an asynchronous exception.. and it's re-thrown as 
> synchronous... the same non-resumability happens! mapException is a 
> particular culprit because of the unsafePerformIO (so you had a good 
> reason to expect resumability, since it's for a pure computation, not in 
> IO)
> - does anyone use mapException?
> - is there some reason that we don't have all "throw"s (synch. or 
> asynch.) "patch up" the thunks?  (memory leaks or serious inefficiency 
> or something?)

In theory you could get a nasty space leak, but it's quite unlikely.  When 
an exception is thrown, instead of just updating each thunk with "raise# 
DivByZero" for example, we would save the current computation in the heap 
to be restarted if the thunk was ever evaluated again.  If the current 
computation refers to a large amount of heap data, technically that's a 
space leak.

So one way to work around this would be to do all rethrows using throwTo. 
In most cases this will have no effect, because the rethrows happen in IO 
code which normally has no enclosing thunks, but in the case of 
mapException and unsafePerformIO it will fix (or work around) the problems 
we have with re-throwing async exceptions.


More information about the Glasgow-haskell-users mailing list