Proposal: Use uninterruptibleMask for cleanup actions in Control.Exception
Simon Marlow
marlowsd at gmail.com
Wed Sep 24 12:51:46 UTC 2014
Ok, sorry for the delay, we still need a resolution on this one.
So thanks to your persuasive comments I think I'm convinced. What
finally tipped me over the edge was this:
https://phabricator.haskell.org/diffusion/GHC/browse/master/libraries/base/Control/Concurrent/QSem.hs;165072b334ebb2ccbef38a963ac4d126f1e08c96$103-112
It turns out I've been a victim of this "bug" myself :-) So let's fix it.
But what is the cost? Adding an uninterruptibleMask won't be free.
In the case of `catch`, since the mask is already built in to the
primitive, we can just change it to be an uninterruptibleMask, and that
applies to handle and onException too. For `finally` we can replace the
mask with an uninterruptibleMask, but for `bracket` we have to add a new
layer of uninterruptibleMask.
Lots of documentation probably needs to be updated. Any chance you
could make a patch and upload it to Phabricator?
Cheers,
Simon
On 05/09/2014 18:34, Eyal Lotem wrote:
> Hey Simon, thanks for the reply!
>
>
> On Fri, Sep 5, 2014 at 6:39 PM, Simon Marlow <marlowsd at gmail.com
> <mailto:marlowsd at gmail.com>> wrote:
>
> Eyal, thanks for bringing up this issue. It's been at the back of
> my mind for a while, but I've never really thought through the
> issues and consequences of changes. So this is a good opportunity
> to do that. You point out (in another email in the thread) that:
>
> A) Cases that were not interruptible will remain the same.
> B) Cases that were interruptible were bugs and will be fixed.
>
> However,
>
> C) Some bugs will turn into deadlocks (unkillable threads)
>
> Being able to recover from bugs is an important property in large
> long-running systems. So this is a serious problem. Hence why I
> always treat uninterruptibleMask with the deepest suspicion.
>
>
> Recovering from various kinds of failures makes a lot of sense. But how
> can you recover from arbitrary invariants of the program being broken?
>
> For example, if you use a bracket on some semaphore monitoring a global
> resource. How do you recover from a bug of leaking semaphore tokens?
>
> Recovering from crashes of whole processes whose internal state can be
> recovered to a fresh, usable state, is a great feature.
> Recovering from thread crashes that share arbitrary mutable state with
> other threads is not practical, I believe.
>
> Let's consider the case where we have an interruptible operation in
> the handler, and divide it into two (er three):
>
> 1. it blocks for a short bounded amount of time.
> 2. It blocks for a long time
> 3. It blocks indefinitely
>
> These are all buggy, but in different ways. Only (1) is fixed by
> adding uninterruptibleMask. (2) is "fixed", but in exchange for an
> unresponsive thread - also undesirable. (3) was a bug in the
> application code, and turns into a deadlock with
> uninterruptibleMask, which is undesirable.
>
>
> I think that (1) is by far the most common and is very prevalent. I
> think 0-time interruptible (that can block but almost never do)
> operations are the most common cleanup handlers.
>
> For (2) and (3), we need to choose the lesser evil:
>
> A) Deadlocks and/or unresponsiveness
> B) Arbitrary invariants being broken and leaks
>
> In my experience, A tends to manifest exactly where the bug is, and is
> therefore easy to debug and mostly a "performance bug" .
> B tends to manifest as difficult to explain behavior elsewhere from
> where the bug actually is, and is usually a "correctness bug", which is
> almost always worse.
>
> Therefore, I think A is a far far lesser evil than B, when (2) and (3)
> are involved.
>
> I'd like to reemphasize that this change will almost always fix the
> problem completely since the most common case is (1), and in rare cases,
> it will convert B to A, which is also, IMO, very desirable.
>
>
> This is as far as I've got thinking through the issues so far. I
> wonder to what extent the programmer can and should mitigate these
> cases, and how much we can help them. I don't want unkillable
> threads, even when caused by buggy code.
>
>
> Cheers,
> Simon
>
>
> On 04/09/2014 16:46, Roman Cheplyaka wrote:
>
> I find your arguments quite convincing. Count that as +1 from me.
>
> Roman
>
>
>
> _________________________________________________
> Libraries mailing list
> Libraries at haskell.org <mailto:Libraries at haskell.org>
> http://www.haskell.org/__mailman/listinfo/libraries
> <http://www.haskell.org/mailman/listinfo/libraries>
>
>
>
>
> --
> Eyal
More information about the Libraries
mailing list