if @block
rd, wr = IO.pipe
@pid = fork do
$0 = "Forked child from Page #{@path}"
rd.close
result = @block.call(@resp.body)
begin
wr.write Marshal.dump(result)
end
wr.close
Run Code Online (Sandbox Code Playgroud)
这是使用fork共享管道的一种非常标准的方法,但是一旦rd.close被调用它就会破坏管道以wr供使用.直到那条管道管道工作正常(我用Pry逐行运行).据我所知,最好关闭叉内的读卡器,以阻止它干扰发送的EOF(我不知道为什么会这样,我只知道这就是练习).
这是我调用生产应用程序的库的一部分.即使它们运行非常相似的代码(只有@block并且@resp将在很大程度上有所不同),库自己的规范从未遇到过这种情况.显然应用程序的代码更复杂,但我看不出它会如何干扰这段代码.我搜索了应用程序所需的其他库,看看是否存在可能会干扰此信号的信号,但我一无所获.
任何人都可以建议问题可能是什么或解决它?我已经尝试捕获Errno::EPIPE异常和retrying,但是这并没有解决它,重新打开管道(我不完全确定如何做到这一点,因为在fork出现后很难将它链接到主进程)清空块,使它不做任何工作......仍然没有快乐.
我还发现(通过对这个问题的评论)标准库中的Ruby的Open3默默地拯救和丢弃,Errno::EPIPE但没有给出提交消息的理由.我不知道它是否相关.
https://github.com/ruby/ruby/blob/e3c288569833b6777e7ecc0bbc26f8e6ca8f2ba7/lib/open3.rb#L268
我们将非常感激地提供任何帮助或见解.
不知道为什么花了这么长时间才得到答复。我怀疑这在当前版本的 ruby 中是“固定的”,因为我无法使用代码的简化版本进行复制,但为了将来的参考,以下是我构建代码的方式:
def test_my_pipes
rd, wr = IO.pipe
fork do
rd.close
sleep 5
wr.write "Hello world"
wr.close
end
wr.close # essential
puts "Waiting for sleepy fork"
puts rd.read
rd.close
end
Run Code Online (Sandbox Code Playgroud)
请注意,在 fork 块的内部和外部,我们都关闭 rd 和 wr。事实上,只有父进程wr.close是必需的,但在不需要时关闭管道的所有末端肯定更好。
如果这段代码仍然无法正常工作,那么我有兴趣看看它们会破坏哪些版本的 ruby。