mask, catch, myThreadId, throwTo

Bertram Felgenhauer bertram.felgenhauer at
Mon Apr 15 22:25:34 CEST 2013

Felipe Almeida Lessa wrote:
> I have some code that is not behaving the way I thought it should.
> The gist of it is
>   sleeper =
>     mask_ $
>     forkIOWithUnmask $ \restore ->
>       forever $
>         restore sleep `catch` throwBack
>   throwBack (Ping tid) = myThreadId >>= throwTo tid . Pong
>   throwBack (Pong tid) = myThreadId >>= throwTo tid . Ping
> Since (a) throwBack is executed on a masked state, (b) myThreadId is
> uninterruptible, and (c) throwTo is uninterruptible, my understanding
> is that the sleeper thread should catch all PingPong exceptions and
> never let any one of them through.

(c) is wrong, throwTo may block, and blocking operations are interruptible.

explains this in some more detail.

The simplest way that throwTo can actually block in your program, as
far as I can see, and one that will only affect the threaded RTS, is
if the sleeper thread and whichever thread is running the other
throwBack are executing on different capabilities; this will always
cause throwTo to block. (You could try looking at a ghc event log to
find out more.)

I last ran into trouble like that with System.Timeout.timeout; for
that function I finally convinced myself that uninterruptibleMask
is the only way to avoid such problems; then throwTo will not be
interrupted by exceptions even when it blocks. Maybe this is the
solution for your problem, too.

Hope that helps,


More information about the Glasgow-haskell-users mailing list