为什么这个程序不返回?还是僵局?

问题描述 投票:0回答:1
这里是完整的程序

module Main where import Control.Concurrent.Async import Control.Concurrent.MVar import System.Environment import System.IO import System.Process main :: IO () main = do args <- getArgs (Just i, Just o, Nothing, p) <- createProcess (proc "socat" args) {std_in = CreatePipe, std_out = CreatePipe} sequence_ [hSetBuffering h NoBuffering | h <- [i, o, stdin, stdout]] hSetEcho stdin False mine <- newEmptyMVar res <- concurrently (do c <- getChar putMVar mine c hPutChar i c) (do other <- hGetChar o mine' <- takeMVar mine return (mine', other)) print $ snd res terminateProcess p
I在不同的终端中启动了两个实例,例如:

$ cabal run myprogram -- TCP-LISTEN:12345,fork - # in terminal 1 $ cabal run myprogram -- TCP-CONNECT:localhost:12345 - # in terminal 2
(按照该顺序)然后我在每个终端中击中一个键(无关紧要),它们都将在一对中打印这两个键(侧面交换)。

有时,尽管我首先击中了终端1中的钥匙,那么终端中的过程不会返回(而终端2中的一个则不返回)。

并非并非特别的编程经验,我不会因为僵局而感到惊讶,但是我看不出这是怎么回事!这是我的观察/推理:

末端2总是返回(至少我从未见过它没有返回); 如果我在

putStrLn "hello"

如果我交换行
    print $ snd res
  • print $ snd res
  • ,“错误”的行为更加频繁;
    我启动的两个过程的两个线程之间可能发生僵局,但是
    
    由于2终端总是返回(特别是它打印了这对),我认为这两个线程肯定没有陷入僵局,
  • 另一个正在运行一个相同的程序,唯一的区别是传递给了催生过程的论点,所以我不明白为什么行为应该不对称,从某种意义上说,如果有僵局,我' d期望它会发生,而不管哪个程序首先收到了击键;
    如果一个线程在调用
    terminateProcess p
    而另一个线程在该程序运行中的同一单个
  • snd res
  • 上,则如何在每个过程的两个线程之间发生僵局?两个呼叫中的每一个都会阻止直到另一个呼叫赶上,否?
    • 
      
    • (Å)在这个非常脱颖而出的示例中,发生这种情况的频率相对较低,但不是太多(似乎有几十次尝试就足够了)。我的确有一个更富裕的例子,似乎对此有更大的影响,但是我认为与此相比,我没有“结构性的”差异,所以我没有发布它以使其更简单,以防万一观察到的行为的原因对专家来说是显而易见的,但是如果认为有用,我可以将其发布。
    • 可能发生的事情是:
    • typinal
      1
      中的A型char
      
      terminal
      1
      中的App
    • 1
    向Socat
  • 1

发送了一个字符

multithreading haskell concurrency deadlock socat
1个回答
0
投票
1

将这些数据发送到Socat

2
  • SOCAT

    2
  • 将数据发送到App
  • 2

    然后您在端子中输入字符2

  • 将这种char发送给Socat

    2 App2

    中的所有线程都完成了,它都打印出炭,并且
  • 终止socat2至关重要的是,它有机会将任何数据发送给socat1

  • app1

    永远等待Socat发送char
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.