Skip to content

Asynchronous exceptions in runInUnboundThread

When you throw an asynchronous exception to a thread which is executing: runInUnboundThread m, m will keep executing and there's no way to kill it.

I propose to catch asynchronous exceptions in runInUnboundThread and throw them to the thread which is executing m. m in turn can decide to catch or ignore them. In case m decides to ignore them or to rethrow them, the exception will be rethrown in the current thread:

runInUnboundThread :: IO a -> IO a
runInUnboundThread action = do
  bound <- isCurrentThreadBound
  if bound
    then do
      mv <- newEmptyMVar
      mask $ \restore -> do
        tid <- forkIO $ Exception.try (restore action) >>= putMVar mv
        let wait = takeMVar mv `Exception.catch` \(e :: SomeException) ->
                     Exception.throwTo tid e >> wait
        wait >>= unsafeResult
    else action

unsafeResult :: Either SomeException a -> IO a
unsafeResult = either Exception.throwIO return

The attached patch implements this behaviour.

(Note there are two other bug-fix patches in the bundle that this patch depends on which can be independently applied.)

Trac metadata
Trac field Value
Version 6.12.3
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component libraries/base
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information