Mat*_*mus 8 concurrency haskell network-programming
我一直试图在使用多个MVar时调试问题,但是没有运气.
我的代码使用两个MVar:一个用于存储服务器的当前状态,另一个用于向客户端线程传递网络事件.但是,在多次连接和断开连接后,服务器会在新客户端连接时停止发送数据(可能是因为网络事件MVar因任何原因而被清空)并最终因错误而跳闸: *** Exception: thread blocked indefinitely in an MVar operation
我在过去几天尝试调试此问题时得出以下结论:
我已将问题隔离到三个文件:
sense
)application
handleClient
,和cleanupClient
)我完全没有想法,因为我只使用modifyMVar和withMVar(所以它肯定永远不会完全留空) - 我唯一的假设是在修改MVar时可能会抛出异常,但我认为这是不太可能的.
任何帮助表示赞赏,这个问题一直困扰着我一段时间.
对于任何可能偶然发现这一点的人来说,一些附加信息thread blocked indefinitely in an MVar operation
并不是那么明智。当包含对 MVar 的引用的每个线程都尝试读取(或写入)该位置、已死亡或正在等待永远被阻止的另一个原语时,就会发生这种情况。例如,线程 1 正在尝试读取 MVara
并等待线程 2,该线程 2 要么已死a
,也尝试读取 MVar ,要么尝试读取b
只能在线程 1 中写入的 MVar 。
下面的代码很高兴永远挂起:
do
a <- newEmptyMVar
forkIO (readMVar a >>= print)
putMVar a $ last $ repeat 0
Run Code Online (Sandbox Code Playgroud)
三天后问题得到解决:实际上与网络或并发代码无关,事实上是我dpSwitch
在 Netwire 中错误地重新实现了 Yampas 造成的。下面发布了更正的代码,供希望实现此功能的任何人使用:
dpSwitch :: (Monoid e, Applicative m, Monad m, T.Traversable col) => (forall wire. a -> col wire -> col (b, wire))
-> col (Wire s e m b c)
-> Wire s e m (a, col c) (Event d)
-> (col (Wire s e m b c) -> d -> Wire s e m a (col c))
-> Wire s e m a (col c)
dpSwitch route wireCol switchEvtGen continuation = WGen $ gen wireCol switchEvtGen
where
gen wires switchEvtGenWire _ (Left x) = return (Left mempty, WGen $ gen wires switchEvtGenWire)
gen wires switchEvtGenWire ws (Right x) = do
let routings = route x wires
wireSteps <- T.sequenceA (fmap (\(wireInput, wire) -> stepWire wire ws (Right wireInput)) routings)
let wireOutputs = T.sequenceA (fmap fst wireSteps)
steppedWires = fmap snd wireSteps
case wireOutputs of
Left wireInhibitedOutput -> return (Left wireInhibitedOutput, WGen $ gen steppedWires switchEvtGenWire)
Right wireResultOutput -> do
(event, steppedSwitchEvtGenWire) <- stepWire switchEvtGenWire ws (Right (x, wireResultOutput))
case event of
Left eventInhibited -> return (Left eventInhibited, WGen $ gen steppedWires steppedSwitchEvtGenWire)
Right NoEvent -> return (wireOutputs, WGen $ gen steppedWires steppedSwitchEvtGenWire)
Right (Event e) -> return (wireOutputs, continuation steppedWires e)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1685 次 |
最近记录: |