如何在单个 ruby 脚本中写入和读取同一个命名管道?

How to write to and read from the same named pipe in a single ruby script?

编辑:我想我解决了这个问题:https://gist.github.com/niuage/c0637b8dd10549a12b6a223dbd5f158a

我可能遗漏了 Process.wait,因此创建了很多僵尸进程。


我有一段代码大部分时间都在工作,但 "locks" 一段时间后它自己,可能是因为竞争条件。

我的代码

pipe = "goals.png"

(1..100).each do |time|
  fork do
    # This runs ffmpeg, and gets it to write 1 frame of a video to the pipe 'goals.png'
    print "before ffmpeg"
    `#{ffmpeg(time, score_crop_options, pipe)}`
    exit
  end

  # Reads from 'pipe'
  print "before read"
  blob = File.read(pipe)
  image = Rocket::Image.from_blob(blob)
  # do stuff with image
end

注意事项:

我的问题

编辑:当脚本被锁定时,我尝试从另一个脚本读取管道,我得到 zsh: fork failed: resource temporarily unavailable。这可能是一个很好的线索...

大多数时候,File.read(pipe) 在 fork 中的代码之前执行,所以它工作得很好,但过了一会儿脚本就停止了:它打印 "before ffmpeg" 并且永远不会到达 "before read"...


首先,我应该使用线程而不是 fork 吗?我可以控制 2 个语句(读取和写入)获得 运行 的顺序以避免竞争条件吗?或者也许它甚至与比赛条件无关,我错过了什么?

这个问题不是由竞争条件引起的,而是僵尸进程太多,因为我没有调用 Process.wait

The parent process should use Process.wait to collect the termination statuses of its children or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

这就是为什么我在尝试从另一个脚本中读取管道时得到 zsh: fork failed: resource temporarily unavailable 的原因。

这里有一些有用的东西:

(1..100) do
  if fork
    # Parent
    image = read_image(pipe)
    # do stuff with image

    Process.wait # I think that's what was missing previously
  else
    # Child
    Open3.popen3(command(time, score_crop_options, pipe)) do |stdin, stdout, stderr, wait_thr|
      # stuff
    end
    exit!(0)
  end
end