Haskell is obsessed with a situation in which he (theoretically) should not

The following is a deadlock error message (* Exception: thread blocked indefinitely in MVar operation). I thought about it step by step and I do not see a problem.

  • In the main thread, an MVAR is created and passed to the manufacturer working in the new thread
  • producer starts and blocks in listenOn, waiting for a connection
  • The main thread continues in the loop and blocks, expecting MVar to receive something.
  • As soon as the manufacturer receives the connection, it continues to cycle in it and, after receiving something from the socket, places it in MVar

Meaning (as I understand it), this should end up with the manufacturer putting something in the MVar, and most importantly waiting for something.

If it gets stuck because listenOn doesn't connect right away, how can I get around this? MVar needs to be created basically, and before the manufacturer branches out so that it can be transferred.

import Control.Concurrent import Network import Network.Socket import System.IO getSockInfo :: Socket -> IO String getSockInfo s = do info <- getPeerName s return $ case info of (SockAddrInet port addr) -> "Addr/Port: " ++ (show addr) ++ " / " ++ (show port) (SockAddrInet6 port flow addr scope) -> "Addr/Port: " ++ (show addr) ++ " / " ++ (show port) ++ "Flow/Scope: " ++ (show flow) ++ " / " ++ (show scope) producer :: MVar String -> IO () producer m = do s <- listenOn (PortNumber 5555) putStrLn "Listening..." info <- getSockInfo s putStrLn $ "Connected to " ++ info h <- socketToHandle s ReadMode loop hm where loop hm = do message <- hGetLine h putMVar m message loop hm main :: IO () main = do withSocketsDo $ do m <- newEmptyMVar prod <- forkIO $ producer m loop m where loop m = do n <- takeMVar m print n loop m 
+7
haskell networking
source share
1 answer

listenOn returns immediately, but does not give you a connected socket, so attempts to use or read from it are not made. I'm not sure why you are not seeing an error message to indicate this, as I do this when you run your code. In any case, the listening thread is likely to die at this point, which leaves the main thread inhibited, since nothing can write to MVar.

Using accept after listenOn to wait for a remote connection should fix this.

+4
source share

All Articles