Errno :: EPIPE:引发了断管异常

iai*_*ain 11 ruby fork pipe

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

我们将非常感激地提供任何帮助或见解.

use*_*769 1

不知道为什么花了这么长时间才得到答复。我怀疑这在当前版本的 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​​。