Safepoint does not work as documented in paper
Simon Marlow
simonmarhaskell at gmail.com
Tue Dec 5 11:36:20 EST 2006
Chris Kuklewicz wrote:
> Simon Marlow wrote:
>
>>Chris Kuklewicz wrote:
>>
>>>One odd problem: The paper on async exception defines:
>>>
>>>safePoint = unblock (return ())
>>>
>>>but this simply does not work in my testing. Ever. Even using
>>>{-# NOINLINE safePoint #-} or "-Onot"
>>>
>>>By comparision, this does work: safepoint = unblock (print "safe")
>>>
>>>So how can such a safePoint be written?
>>
>>The window in 'unblock (return ())' is tiny, I'm not really surprised if nothing ever gets through it. You might have more luck with 'unblock yield'.
>>
>>(BTW, I think glasgow-haskell-users at haskell.org is a more appropriate list, so I'm replying there instead).
>>
>>Cheers,
>> Simon
>
>
> That works, thanks.
>
> It is funny, the killThread thread is halted and waiting for the async signal to
> be delivered, and the running thread got through eleven (unblock (print
> "sleeper")) statements before noticing that it had been told to die. Using
> your (unblock yield) worked
>
> I had thought that "unblock" would always check the queue of incoming async
> signals but this is obviously not the case. The "Asynchronous Exceptions in
> Haskell" paper says:
>
> "As soon as a thread exits the scope of a block, and at regular intervals during
> execution inside unblock, its pending exceptions queue must be checked. If there
> are pending exceptions, the first one is removed from the queue and delivered to
> the thread."
There's one major difference between what's described in that paper and what's
actually implemented: GHC's throwTo is synchronous; it doesn't return until the
exception has been delivered.
We went to-and-fro on this issue several times during the design, and I forget
the reason we finally went with the asynchronous version of throwTo for the
paper; maybe we were thinking about distributed applications where a synchronous
throwTo would be more difficult to implement. The synchronous version is often
easier to program with, so that's what we've got in GHC, and you can get the
asynchronous version by adding a forkIO around it.
Now, this leads to the reason why 'unblock (return ())' doesn't work as you
expected. When a thread executes throwTo and the target thread is inside a
block, the source thread blocks. when the target thread hits an unblock, it
wakes up the source thread, but unless it context switches before entering a
blocked state again, when the source thread finally runs it'll find the target
thread in a blocked state and have to go back to sleep.
> ...which is why I have the wrong expectation. Is there a better resource for
> how GHC actually implements block/unblock/throwTo ? Searching for throwTo on
> the wiki gets me nothing.
I should write something in the commentary sometime...
Cheers,
Simon
More information about the Glasgow-haskell-users
mailing list