Felipe Almeida Lessa | 15 Apr 21:57 2013
Picon

mask, catch, myThreadId, throwTo

Hey!

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.

However, that's not what I am seeing.  Running with -threaded and at
least -N2 I can reliably get sleeper to be killed.  Please see the
complete code at:

  https://gist.github.com/meteficha/5390079

The expected result is 100 Pongs and 0 Pings.  Running with -N1 that's
what I get.  Running with -N2 I get a few Pongs and then 1 Ping.
Running with -N3 or more usually gives me just 1 Ping and not a single
Pong.
(Continue reading)

Bertram Felgenhauer | 15 Apr 22:25 2013

Re: mask, catch, myThreadId, throwTo

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.

  http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#v:throwTo

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
(Continue reading)

Felipe Almeida Lessa | 15 Apr 22:34 2013
Picon

Re: mask, catch, myThreadId, throwTo

Thanks a lot, you're correct!  The trouble is, I was misguided by the
"Interruptible operations" note [1] which states that

    The following operations are guaranteed not to be interruptible:
        ... * everything from Control.Exception ...

Well, it seems that not everything from Control.Exception fits the bill.

Thanks, =)

[1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:14

On Mon, Apr 15, 2013 at 5:25 PM, Bertram Felgenhauer
<bertram.felgenhauer <at> googlemail.com> wrote:
> 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
(Continue reading)

Edward Z. Yang | 15 Apr 22:38 2013
Picon

Re: mask, catch, myThreadId, throwTo

Sounds like those docs need to be fixed, in that case.

Edward

Excerpts from Felipe Almeida Lessa's message of Mon Apr 15 13:34:50 -0700 2013:
> Thanks a lot, you're correct!  The trouble is, I was misguided by the
> "Interruptible operations" note [1] which states that
> 
>     The following operations are guaranteed not to be interruptible:
>         ... * everything from Control.Exception ...
> 
> Well, it seems that not everything from Control.Exception fits the bill.
> 
> Thanks, =)
> 
> [1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:14
> 
> On Mon, Apr 15, 2013 at 5:25 PM, Bertram Felgenhauer
> <bertram.felgenhauer <at> googlemail.com> wrote:
> > 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
> >>
(Continue reading)

Edward Z. Yang | 16 Apr 23:20 2013
Picon

Re: mask, catch, myThreadId, throwTo

OK, I've updated the docus.

Excerpts from Felipe Almeida Lessa's message of Mon Apr 15 13:34:50 -0700 2013:
> Thanks a lot, you're correct!  The trouble is, I was misguided by the
> "Interruptible operations" note [1] which states that
> 
>     The following operations are guaranteed not to be interruptible:
>         ... * everything from Control.Exception ...
> 
> Well, it seems that not everything from Control.Exception fits the bill.
> 
> Thanks, =)
> 
> [1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:14
> 
> On Mon, Apr 15, 2013 at 5:25 PM, Bertram Felgenhauer
> <bertram.felgenhauer <at> googlemail.com> wrote:
> > 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
(Continue reading)

Felipe Almeida Lessa | 16 Apr 23:27 2013
Picon

Re: mask, catch, myThreadId, throwTo

Nice, thanks, Edward =).

On Tue, Apr 16, 2013 at 6:20 PM, Edward Z. Yang <ezyang <at> mit.edu> wrote:
> OK, I've updated the docus.
>
> Excerpts from Felipe Almeida Lessa's message of Mon Apr 15 13:34:50 -0700 2013:
>> Thanks a lot, you're correct!  The trouble is, I was misguided by the
>> "Interruptible operations" note [1] which states that
>>
>>     The following operations are guaranteed not to be interruptible:
>>         ... * everything from Control.Exception ...
>>
>> Well, it seems that not everything from Control.Exception fits the bill.
>>
>> Thanks, =)
>>
>> [1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:14
>>
>> On Mon, Apr 15, 2013 at 5:25 PM, Bertram Felgenhauer
>> <bertram.felgenhauer <at> googlemail.com> wrote:
>> > 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
(Continue reading)


Gmane