Errno :: EPIPE:引发了断开的管道异常

时间:2017-06-18 16:33:23

标签: ruby pipe fork

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

这是使用fork共享管道的一种非常标准的方法,但只要调用rd.close,就会破坏wr使用的管道。直到那条管道管道工作正常(我用Pry逐行运行)。据我所知,最好关闭阅读器内部的阅读器,以阻止它干扰EOF被发送(我不知道为什么会有效,我只知道这就是练习)。

这是我调用生产应用程序的库的一部分。即使它们运行非常相似的代码,库自己的规范也从未遇到过这种情况(只有@block@resp会有很大差异)。显然应用程序的代码更复杂,但我看不出它会如何干扰这段代码。我搜索了应用程序所需的其他库,看看是否有任何可能会干扰信号的信号,但我什么都没发现。

任何人都可以提出问题或解决问题吗?我已经尝试捕获Errno::EPIPE异常和retry但是这并没有解决它,重新打开管道(我不完全确定如何做到这一点,因为叉子发生之后它''很难将它链接到主要过程),清空块以便它不做任何工作......仍然没有快乐。

我还发现(通过对this question的评论)标准库中的Ruby的Open3默默地拯救并删除了Errno::EPIPE但没有给出提交消息的理由。我不知道它是否相关。 https://github.com/ruby/ruby/blob/e3c288569833b6777e7ecc0bbc26f8e6ca8f2ba7/lib/open3.rb#L268

非常感谢任何帮助或见解。

1 个答案:

答案 0 :(得分: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

请注意,在fork块的内部和外部,我们都关闭了rd和wr。实际上,只有父进程wr.close是必不可少的,但是在不需要时关闭管道的所有末端肯定更好。

如果此代码仍然无法破解,请查看它们所针对的红宝石版本。