来自孩子的stdout的Ruby管道未关闭/如何检测空管道

时间:2018-08-12 17:31:45

标签: ruby pipe fork exec stdout

我有一个包含任意数据的文件setuptools_scm。我分叉,将testin连接到父管道,然后执行stdout来读取文件并将其推入管道。然后,从父级管道中以其dd执行另外两个子级。然后,父级从第一个进程中读取字节,并将其写入其他两个子级。

我的问题是,直到循环永远不会结束。如果我将第一个进程中的stdin发送到管道,则该条件将卡在下一个#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') 分叉了第一个过程并使用pipe1w.close作为循环条件得以解决–收到了EOF,循环结束。 / p>

1 个答案:

答案 0 :(得分:1)

您尚未在父进程中关闭pipe1w

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