并发Haskell异常

时间:2017-11-17 13:39:40

标签: multithreading haskell exception concurrency exception-handling

如何在并发Haskell程序中提供异常?

我们假设我们有一个进程,有多个线程,其中一个通过TCP连接与某些东西进行交互,我们得到一个信号(比如在* nix系统上)。

此信号将传递给哪个(绿色)线程?

是否会将其发送给"使用"插座或"主要"指定的线程将接收,它必须明确地执行throwTo将异常发送到该(绿色)线程?

1 个答案:

答案 0 :(得分:1)

POSIX信号和Haskell异常之间没有自动对应关系。

为了将信号转换为异常,需要有一个信号处理程序来执行此操作 - 向其中一个Haskell线程抛出异常。哪个线程获得异常完全取决于信号处理程序的设置方式。

默认情况下,GHC仅为SIGINT设置这样的处理程序,该信号将异常传递给主线程。

你可以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.Signals
import System.Mem.Weak (deRefWeak)

newtype SignalException = SignalException Signal
  deriving (Show, Typeable)
instance Exception SignalException

installSignalHandlers :: 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
  ...

但您也可以获得创意并更改处理程序以将信号传递给其他线程。例如。如果只有一个线程使用套接字,则可以确保该线程获得异常。或者,根据您感兴趣的信号,也许您可​​以figure out the relevant thread based on the siginfo_t structure(参见sigaction(2)) - 也许是si_fd字段?