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