Final bikeshedding call: Fixing Control.Exception.bracket

Simon Marlow marlowsd at gmail.com
Sun Nov 23 21:53:13 UTC 2014


On 23/11/14 20:23, Edward Kmett wrote:
> This is predicated on a lot of assumptions though:
>
> * That nobody else has closed over a reference to the handle in a way
> that prevents the GC from freeing it.

Yup

> * That file handles are the only resources we are concerned with.

Oh no, I'm not assuming that - this corner of the discussion is just 
about hClose.  Of course it doesn't extend to non-finalized resources.

> * That eventual clean up is okay when things go wrong.

Well, I think this is not at all clear either way.  Which would you 
rather have:

  - cleanup that might block in an unkillable way

  - cleanup performed asynchronously while the current thread
    remains killable.

Clearly only the programmer can answer that, it depends on whether async 
cleanup is acceptable; if it is, this is almost certainly preferable, 
because we get to keep responsiveness.

> These often hold, and at least we can say they hold for file handles for
> all but the most resource constrained of users, but I think ultimately
> there is a fundamental tension between real actual finalization
> guarantees and having killThread return in a timely manner when its
> target goes off the reservation.
>
> With files we can get into situations where just bracketing "badly"
> still just works. With other resources though its a fair bit more hazardous.
>
> Whether that warrants a change in the default form of bracket is another
> matter.

Indeed.  To move this discussion forward, I would like to see someone 
catalogue common and existing use cases of bracket and document their 
buginess (or lack thereof) under the current and proposed semantics.  Do 
it on a wiki page, then we'll have something concrete to argue over.  I 
would do this myself but for lack of time, but I'll try to contribute to 
the discussion nonetheless.

Cheers,
Simon


> -Edward
>
> On Sun, Nov 23, 2014 at 1:57 PM, Simon Marlow <marlowsd at gmail.com
> <mailto:marlowsd at gmail.com>> wrote:
>
>     On 23/11/14 17:46, John Lato wrote:
>
>
>
>         On Sun Nov 23 2014 at 7:09:10 AM Simon Marlow
>         <marlowsd at gmail.com <mailto:marlowsd at gmail.com>
>         <mailto:marlowsd at gmail.com <mailto:marlowsd at gmail.com>>> wrote:
>
>              On 21/11/14 17:22, Gregory Collins wrote:
>               > New post from Yuras provides food for thought:
>               >
>         https://github.com/Yuras/io-____region/wiki/Handling-%28async%____29-exceptions-in-haskell:-____pushing-bracket-to-the-limits
>         <https://github.com/Yuras/io-__region/wiki/Handling-%28async%__29-exceptions-in-haskell:-__pushing-bracket-to-the-limits>
>
>         <https://github.com/Yuras/io-__region/wiki/Handling-%28async%__29-exceptions-in-haskell:-__pushing-bracket-to-the-limits
>         <https://github.com/Yuras/io-region/wiki/Handling-%28async%29-exceptions-in-haskell:-pushing-bracket-to-the-limits>>
>               >
>               > In particular he points out a case for which
>         uninterruptibleMask will
>               > cause unkillable threads: let's say hClose blocks
>         flushing the
>              output to
>               > a file, but the write fails because of a hardware error
>         and blocks
>               > forever. (Alternatively, imagine the file is on NFS and
>         you get a
>              cable
>               > cut between the two machines). The thread executing
>         hClose in the
>               > cleanup action becomes unkillable.
>
>              Yes, and furthermore hClose is not "buggy": even if it is
>         interrupted by
>              an async exception, the file descriptor will still be
>         closed by the
>              finalizer.  This is not something you want to do a lot, of
>         course, but
>              as a backup plan for the rare case of an async exception
>         killing the
>              cleanup action it's fine.
>
>
>         This is not entirely correct.  If another thread is holding the MVar
>         when hClose is called, and it is blocked in takeMVar, if an async
>         exception arrives takeMVar will be interrupted and the file
>         descriptor
>         will never be closed.  Arguably that situation shouldn't happen
>         except
>         in poorly-designed programs, but I can provide at least one example
>         where it appears to be a viable architecture, and I'm not
>         convinced it
>         would never happen in practice.
>
>
>     Handles have a finalizer that closes the Handle sometime after its
>     last use, so it's not possible to leak a Handle permanently.
>     There's an unpredictable delay before it gets closed, which is why
>     we don't rely on this to close our Handles normally, but I'm arguing
>     it's fine to rely on this to close Handles in the rare case where
>     hClose is interrupted.
>
>              So arguably uninterruptibleMask is not what we want for hClose.
>
>
>         Is there any way to fix the issue I describe besides preventing
>         async
>         exceptions from arising while blocked on the MVar?  Although I
>         do agree
>         we don't want to put uninterruptibleMask inside hClose (long
>         ramble at
>         http://johnlato.blogspot.ca/__2014/11/exception-handling-__and-cleanup.html
>         <http://johnlato.blogspot.ca/2014/11/exception-handling-and-cleanup.html>)
>
>
>     In the absence of a finalizer, besides uninterruptibleMask the only
>     alternative that springs to mind is to fork a thread to finish the
>     cleanup when an async exception strikes; which is actually not a bad
>     solution as long as you don't rely on the resource being released in
>     the original thread.
>
>     Cheers,
>     Simon
>
>         John
>
>
>              Cheers,
>              Simon
>
>
>               > G
>               >
>               > On Thu, Nov 20, 2014 at 7:24 AM, Simon Marlow
>         <marlowsd at gmail.com <mailto:marlowsd at gmail.com>
>              <mailto:marlowsd at gmail.com <mailto:marlowsd at gmail.com>>
>               > <mailto:marlowsd at gmail.com <mailto:marlowsd at gmail.com>
>         <mailto:marlowsd at gmail.com <mailto:marlowsd at gmail.com>>>> wrote:
>               >
>               >     On 19/11/2014 23:07, Ganesh Sittampalam wrote:
>               >
>               >         On 13/11/2014 10:44, Simon Marlow wrote:
>               >
>               >             On 13/11/2014 07:47, Merijn Verstraaten wrote:
>               >
>               >
>               >                 A new version would look like:
>               >
>               >                 bracket before after thing =
>               >                      mask $ \restore -> do
>               >                        let atomicAfter =
>         uninterruptibleMask . after
>               >                        a <- before
>               >                        r <- restore (thing a) `onException`
>              atomicAfter a
>               >                        _ <- atomicAfter a
>               >                        return r
>               >
>               >                 Slightly different versions are possible
>         and the
>              other
>               >                 relevant
>               >                 bracketing functions mentioned in this
>         thread can be
>               >                 treated similarly.
>               >
>               >
>               >             Since we would need this for catch too, the
>         sensible
>              thing
>               >             to do (if we
>               >             decide to go ahead with this) would be to
>         change the
>               >             implementation of
>               >             catch in the RTS from masking the exception
>         handler to
>               >             uninterruptibleMask.  That would mean that
>         at least for
>               >             catch there
>               >             would be no additional overhead, and it
>         would make the
>               >             modifications to
>               >             the other operations simpler in some cases.
>               >
>               >
>               >         If this isn't done in the RTS, is there a
>         possibility of
>              an async
>               >         exception slipping in between the exception handler
>              starting and the
>               >         uninterruptibleMask starting?
>               >
>               >
>               >     No, because the exception handler is masked.
>               >
>               >     Cheers,
>               >     Simon
>               >
>               >     _____________________________________________________
>               >     Libraries mailing list
>               > Libraries at haskell.org <mailto:Libraries at haskell.org>
>         <mailto:Libraries at haskell.org <mailto:Libraries at haskell.org>>
>              <mailto:Libraries at haskell.org
>         <mailto:Libraries at haskell.org> <mailto:Libraries at haskell.org
>         <mailto:Libraries at haskell.org>>__>
>               > http://www.haskell.org/______mailman/listinfo/libraries
>         <http://www.haskell.org/____mailman/listinfo/libraries>
>              <http://www.haskell.org/____mailman/listinfo/libraries
>         <http://www.haskell.org/__mailman/listinfo/libraries>>
>               >
>           <http://www.haskell.org/____mailman/listinfo/libraries
>         <http://www.haskell.org/__mailman/listinfo/libraries>
>              <http://www.haskell.org/__mailman/listinfo/libraries
>         <http://www.haskell.org/mailman/listinfo/libraries>>>
>               >
>               >
>               >
>               >
>               > --
>               > Gregory Collins <greg at gregorycollins.net
>         <mailto:greg at gregorycollins.net>
>              <mailto:greg at gregorycollins.__net
>         <mailto:greg at gregorycollins.net>> <mailto:greg at gregorycollins.
>         <mailto:greg at gregorycollins.>____net
>              <mailto:greg at gregorycollins.__net
>         <mailto:greg at gregorycollins.net>>>>
>
>              ___________________________________________________
>              Libraries mailing list
>         Libraries at haskell.org <mailto:Libraries at haskell.org>
>         <mailto:Libraries at haskell.org <mailto:Libraries at haskell.org>>
>         http://www.haskell.org/____mailman/listinfo/libraries
>         <http://www.haskell.org/__mailman/listinfo/libraries>
>              <http://www.haskell.org/__mailman/listinfo/libraries
>         <http://www.haskell.org/mailman/listinfo/libraries>>
>
>
>     _________________________________________________
>     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>
>
>



More information about the Libraries mailing list