Opened 9 years ago

Closed 9 years ago

#4400 closed proposal (fixed)

Asynchronous exceptions in runInUnboundThread

Reported by: basvandijk Owned by: simonmar
Priority: high Milestone: 7.4.1
Component: libraries/base Version: 6.12.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


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.)

Attachments (1)

exceptions_in_runInUnboundThread.dpatch (53.0 KB) - added by basvandijk 9 years ago.

Download all attachments as: .zip

Change History (5)

Changed 9 years ago by basvandijk

comment:1 Changed 9 years ago by basvandijk

Thread on the libraries list.

comment:2 Changed 9 years ago by basvandijk

Status: newpatch

The deadline for this proposal has passed. There was little interest but no objections so I'm moving the ticket to 'patch'.

comment:3 Changed 9 years ago by simonmar

Milestone: 7.2.1
Owner: set to simonmar
Priority: normalhigh

comment:4 Changed 9 years ago by simonmar

Resolution: fixed
Status: patchclosed

Pushed, thanks.

Thu Oct 14 22:05:46 BST 2010  Bas van Dijk <>
  * Use throwIO instead of throw in runInBoundThread and runInUnboundThread
Thu Oct 14 22:23:25 BST 2010  Bas van Dijk <>
  * There's no need to explicitly check for blocked status in runInUnboundThread when we have mask
Thu Oct 14 22:27:23 BST 2010  Bas van Dijk <>
  * Catch exceptions in current thread and throw them to the forked thread in runInUnboundThread
Note: See TracTickets for help on using tickets.