Concurrent Haskell exceptions Concurrent Haskell exceptions multithreading multithreading

Concurrent Haskell exceptions


There is no automatic correspondence between POSIX signals and Haskell exceptions.

In order for a signal to be turned into an exception, there needs to be a signal handler that will do just that — throw an exception to one of the Haskell threads. Which thread gets the exception depends entirely on how the signal handler is set up.

By default, GHC sets up such a handler for SIGINT only, and that signal delivers the exception to the main thread.

You can install similar handlers for the other signals:

import Control.Concurrent (mkWeakThreadId, myThreadId)import Control.Exception (Exception(..), throwTo)import Control.Monad (forM_)import Data.Typeable (Typeable)import System.Posix.Signalsimport System.Mem.Weak (deRefWeak)newtype SignalException = SignalException Signal  deriving (Show, Typeable)instance Exception SignalExceptioninstallSignalHandlers :: IO ()installSignalHandlers = do  main_thread_id <- myThreadId  weak_tid <- mkWeakThreadId main_thread_id  forM_ [ sigABRT, sigBUS, sigFPE, sigHUP, sigILL, sigQUIT, sigSEGV,          sigSYS, sigTERM, sigUSR1, sigUSR2, sigXCPU, sigXFSZ ] $ \sig ->    installHandler sig (Catch $ send_exception weak_tid sig) Nothing  where    send_exception weak_tid sig = do      m <- deRefWeak weak_tid      case m of        Nothing  -> return ()        Just tid -> throwTo tid (toException $ SignalException sig)main = do  installSignalHandlers  ...

But you can also get creative and change the handler to deliver the signal to some other thread. E.g. if there is only one thread working with sockets, you can make sure that thread gets the exception. Or, depending on the signal you're interested in, maybe you can figure out the relevant thread based on the siginfo_t structure (see sigaction(2)) — perhaps the si_fd field?