如何在并发Haskell程序中提供异常?
我们假设我们有一个进程,有多个线程,其中一个通过TCP连接与某些东西进行交互,我们得到一个信号(比如在* nix系统上)。
此信号将传递给哪个(绿色)线程?
是否会将其发送给"使用"插座或"主要"指定的线程将接收,它必须明确地执行throwTo
将异常发送到该(绿色)线程?
答案 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字段?