Ruby 来自 child 的标准输出的管道不是 closing/how 来检测空管道

Ruby pipe from child's stdout not closing/how to detect empty pipe

我有一个包含任意数据的文件 testin。我分叉,将 stdout 连接到 parent 的管道,然后执行 dd 以读取文件并将其推入管道。然后另外两个 children 与来自 parent 的管道中的 stdin 类似地执行。 parent 然后从第一个进程读取字节并将它们写入另外两个 children.

我的问题是 until 循环永远不会结束。如果我将 #closed? 作为条件从第一个进程发送到管道,它会卡在下一个 #read 等待进程完成后的更多数据。如果我发送 #eof? 它会卡在 #eof?.

为什么我没有收到 EOF 或者为什么管道没有关闭?我应该如何检测没有更多数据?

pipe1r, pipe1w = IO.pipe
pid1 = fork do
    $stdout.reopen(pipe1w)
    exec 'dd', 'if=testin'
end

pipe2r, pipe2w = IO.pipe
pid2 = fork do
    $stdin.reopen(pipe2r)
    exec 'dd', 'of=testout1'
end

pipe3r, pipe3w = IO.pipe
pid3 = fork do
    $stdin.reopen(pipe3r)
    exec 'dd', 'of=testout2'
end

until pipe1r.closed?
    byte = pipe1r.read(1)
    pipe2w.write(byte)
    pipe3w.write(byte)
end
pipe2w.close
pipe3w.close

pid, status = Process.wait2(pid1)
puts 'Process 1 was a ' + (status.success? ? 'success' : 'failure')

pid, status = Process.wait2(pid2)
puts 'Process 2 was a ' + (status.success? ? 'success' : 'failure')

pid, status = Process.wait2(pid3)
puts 'Process 3 was a ' + (status.success? ? 'success' : 'failure')

已解决: 根据 matthewd 的回答,pipe1w.close 在分叉第一个进程并使用 until pipe1r.eof? 作为循环条件修复它后——接收到 EOF 并且循环结束。

您还没有在父进程中关闭pipe1w

你的循环之前需要一个pipe1w.close,否则管道永远不会为空:分叉进程已经停止写入(并关闭它的副本),但父进程仍然可以写入它。