Thread locked endlessly in MVar operation

I am trying to debug a problem when using multiple MVars, but no luck.

My code uses two MVars: one to store the current state of the servers, and the other to send network events to client streams and vice versa. However, after connecting and disconnecting several times, the server stops sending data when new clients connect (presumably due to the fact that MVar network events are being emptied for some reason) and, ultimately, it disconnects with an error: *** Exception: thread blocked indefinitely in an MVar operation

Over the past few days, I decided to do the following:

  • Functions used to modify MVar (s) do not throw an exception
  • The problem does not occur until the client connects or connects and then disconnects
  • The problem occurs accidentally (sometimes several clients can connect and then disconnect, in other cases this happens immediately).

I highlighted a problem for three files:

I completely exclude ideas, since I only use the MVar and MVar modifications (so, of course, it should never be left completely empty). My only assumption is that perhaps an exception occurs when the MVar changes, but I think this is unlikely.

Any help is appreciated, this issue has been bugging me for some time.

+7
concurrency haskell network-programming
source share
3 answers

Three days later, and its solution: in fact, it was not connected with either the network or the concurrency code, but with inflation caused by the incorrect re-implementation of Yampas dpSwitch in Netwire. The corrected code is listed below for everyone who wants to implement this function:

 dpSwitch :: (Monoid e, Applicative m, Monad m, T.Traversable col) => (forall wire. a -> col wire -> col (b, wire)) -> col (Wire sembc) -> Wire sem (a, col c) (Event d) -> (col (Wire sembc) -> d -> Wire sema (col c)) -> Wire sema (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) 
+4
source share

For those who might stumble upon this, some additional information thread blocked indefinitely in an MVar operation is actually not so smart. This happens when each thread containing a link to MVar tries to read (or write) to this place, dies, or waits for another primitive that is blocked forever. for example, stream 1 tries to read MVar a and waits in stream 2, which is either dead, or tries to read MVar a , or tries to read MVar a, which can only be written to stream 1.

The following code hangs happily forever:

 do a <- newEmptyMVar forkIO (readMVar a >>= putStrLn) putMVar a $ last $ repeat 0 
+3
source share

I think I see the problem - it is in Server.hs. You have operations that perform network IO inside a call withMVar . Now imagine that IO is blocking effectively forever. You also do not get an exception that causes var to be replaced, and the operation does not execute normally and does not replace var, and therefore you are stuck.

In general, you should not do any significant operations in a call to withMVar , even if you can. And if you perform such operations, you need to be sure that you effectively protect them with timeouts, etc., so that you can be sure that they always end one way or another.

+2
source share

All Articles