Haskell在理论上不应该这样的情况下陷入僵局

以下内容会产生死锁错误消息(*异常:MVar操作中无限期阻塞的线程)。 我一直在想,它并没有看到这个问题。

  • 在主线程上,创建一个MVar,并将其交给生产者,并在新线程上运行
  • 制片人开始,并在listenOn上阻止,等待连接
  • 主线程继续进入循环,并阻塞,等待MVar接收一些东西
  • 一旦生产者获得连接,它就会继续进入它的循环,并且在从套接字接收到一些东西后,将它放入MVar中
  • 意义(据我了解),它应该最终与生产者在MVar中放置一些东西,并主要等待接收一些东西。

    如果因为listenOn没有立即连接而卡住了,我该如何解决这个问题? MVar需要在main中创建,并且在生成器被分离之前就可以传入。

    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 h m
        where loop h m = do
            message <- hGetLine h
            putMVar m message
            loop h m
    
    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
    

    listenOn立即返回,但不会给你一个连接的套接字,所以试图使用它或从它读取失败。 我不知道为什么你没有看到一条错误消息来表明这一点,因为我在运行代码时会这样做。 在任何情况下,监听线程都可能在这一点上死亡,这导致主线程死锁,因为没有任何事情可以写入MVar。

    listenOn之后使用accept来等待远程连接应该解决这个问题。

    链接地址: http://www.djcxy.com/p/80647.html

    上一篇: Haskell is getting deadlocked in a situation it (in theory) shouldn't be

    下一篇: How to prevent ctrl+c killing spawned processes in Java