[Haskell-cafe] Printing of asynchronous exceptions to stderr

Bas van Dijk v.dijk.bas at gmail.com
Wed Nov 10 02:54:48 EST 2010


On Tue, Nov 9, 2010 at 5:37 PM, Mitar <mmitar at gmail.com> wrote:
> Why is ThreadKilled not displayed by RTS when send to thread (and
> unhandled), but any other exception is?

A ThreadKilled exception is not printed to stderr because it's not
really an error and should not be reported as such. It is also clear
how to handle a ThreadKilled: just abort the thread and silently
terminate. All other exceptions raised in or thrown to the thread
which are not handled by the thread itself should be considered errors
and reported as such.

To see what happens under the hood look at the implementation of
forkIO by clicking on the 'Source' link next to the type signature:

http://hackage.haskell.org/packages/archive/base/4.2.0.2/doc/html/Control-Concurrent.html#v%3AforkIO

The 'action_plus' that is forked catches all exceptions and handles
them with childHandler:
...
  where
    action_plus = catchException action childHandler

childHandler in turn calls real_handler to handle the exception but
registers an exception handler so that exceptions raised by the
real_handler are handled again recursively:

childHandler :: SomeException -> IO ()
childHandler err = catchException (real_handler err) childHandler

Now real_handler handles the exceptions BlockedIndefinitelyOnMVar,
BlockedIndefinitelyOnSTM and ThreadKilled by just returning. All other
exceptions are reported:

real_handler :: SomeException -> IO ()
real_handler se@(SomeException ex) =
  -- ignore thread GC and killThread exceptions:
  case cast ex of
  Just BlockedIndefinitelyOnMVar        -> return ()
  _ -> case cast ex of
       Just BlockedIndefinitelyOnSTM    -> return ()
       _ -> case cast ex of
            Just ThreadKilled           -> return ()
            _ -> case cast ex of
                 -- report all others:
                 Just StackOverflow     -> reportStackOverflow
                 _                      -> reportError se

> For example, I am using custom exceptions to signal different kinds of
> thread killing. Based on those my threads cleanup in different ways.
> But after they cleanup they keep "running". Not really running as
> their computations were interrupted. But simply hanging there. And if
> then new custom exception arrives it is not handled anymore (as it is
> after my normal exception handlers already cleaned everything) and it
> is printed to stderr.

What do you mean by "hanging there". Are they blocked on an MVar?

> Now I added  "`finally` throwIO ThreadKilled" at the end of my cleanup
> computations to really kill the thread. So that possible later
> exceptions are not delivered anymore.

That shouldn't be necessary. If the cleanup action is the last action
of the thread then the thread will terminate when it has performed the
cleanup.

> Why it is not so that after all computations in a thread finish,
> thread is not killed/disposed of?

It actually should. I think any other behavior is a bug.

It would help if you could show us your code (or parts of it).

Regards,

Bas


More information about the Haskell-Cafe mailing list