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?