[Haskell-cafe] Is withAsync absolutely safe?
Roman Cheplyaka
roma at ro-che.info
Mon Jul 29 09:34:10 CEST 2013
* Bertram Felgenhauer <bertram.felgenhauer at googlemail.com> [2013-07-28 18:11:54+0200]
> Roman Cheplyaka wrote:
> > Can withAsync guarantee that its child will be terminated if the thread
> > executing withAsync gets an exception?
> >
> > To remind, here's an implementation of withAsync:
> >
> > withAsyncUsing :: (IO () -> IO ThreadId)
> > -> IO a -> (Async a -> IO b) -> IO b
> > -- The bracket version works, but is slow. We can do better by
> > -- hand-coding it:
> > withAsyncUsing doFork = \action inner -> do
> > var <- newEmptyTMVarIO
> > mask $ \restore -> do
> > t <- doFork $ try (restore action) >>= atomically . putTMVar var
> > let a = Async t (readTMVar var)
> > r <- restore (inner a) `catchAll` \e -> do cancel a; throwIO e
> > cancel a
> > return r
> >
> > I am interested in the case when an exception arrives which transfers
> > control to 'cancel', and then another exception arrives to the same
> > thread. Even though 'catchAll' (which is a type-restricted synonym for
> > catch) masks the exception handler, 'throwTo' inside 'cancel' is
> > interruptible (as stated by the documentation).
> >
> > Will this scenario lead to a thread leakage?
>
> Yes. I guess that 'cancel' should use 'uninterruptibleMask_', but it's a
> hard call to make (if an async action becomes unresponsive, do we want
> to risk not being able to deliver any exceptions to the controlling
> thread just because it wants to terminate the async action?)
Fair point.
What if we fork a new thread, shield it from exceptions using
uninterruptibleMask_, and let it to kill every other thread (however long
that may take)?
It will change the semantics a bit (the cleanup will be asynchronous),
but I'm not sure if it can be a problem.
A hybrid (but complicated) approach should also be possible.
Roman
More information about the Haskell-Cafe
mailing list