【问题标题】:Concurrent Haskell exceptions并发 Haskell 异常
【发布时间】:2018-05-01 07:23:24
【问题描述】:

如何在并发 Haskell 程序中传递异常?

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

这个信号将被传递到哪个(绿色)线程?

它会被传递给正在“使用”套接字的线程还是“主”指定线程将接收并且它必须显式执行throwTo 以将异常发送到该(绿色)线程?

【问题讨论】:

标签: multithreading haskell exception concurrency exception-handling


【解决方案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 字段?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    相关资源
    最近更新 更多