[reactive] Re: black hole detection and concurrency

Bertram Felgenhauer bertram.felgenhauer at googlemail.com
Mon Dec 29 01:26:47 EST 2008

Peter Verswyvelen wrote:
> I fail to understand this part of the code:
>            case fromException e of
>                Just ThreadKilled -> do
>                    myThreadId >>= killThread
>                    unblock (race a b)
> So the current thread gets killed synchronously, then then the race function
> is evaluated again? The latter I don't get.

Let's look at what happens when an asynchronous exception arrives.

The current thread gets killed. It gets killed asynchronously; as far
as the RTS knows, the exceptionit might happen inside a pure computation
which may be accessible to other threads. This means that the RTS has to
patch things up so that reentering the corresponding thunks continues
the computation - because another thread might need the value later. It
does that by traversing the stack and turning update frames into ap
nodes on the heap, and linking the entered thunks to those using an
indirection (again, see RaiseAsync.c for details).

Now in fact, IO actions are indistinguishable from pure computations by
the RTS, so this mechanism also makes IO actions resumable, in
principle, if you can access the corresponding thunk somehow. Normally
you can't - there is no reference to that thunk - but unsafePerformIO
gives you that reference.

So in the above example, the current thread gets killed. However, the IO
action (suspended right before the 'unblock (race a b)') is still
accessible through the unsafePerformIO thunk. When another thread enters
that thunk, execution resumes at that point. It may also be the same
thread if it caught the exception further down the stack and later
enters the unsafePerformIO thunk again.

I don't understand all the interactions here - I don't know why the code
is racy in the parallel RTS.


More information about the Glasgow-haskell-users mailing list