【问题标题】:Errno::EPIPE: Broken pipe exception is raisedErrno::EPIPE:引发了损坏的管道异常
【发布时间】:2017-11-20 21:04:38
【问题描述】:
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

这是用叉子共享管道的一种非常标准的方式,但是一旦调用rd.close,它就会破坏管道以供wr 使用。直到那条线,管道才能正常工作(我用 Pry 逐行运行它)。据我所知,关闭分叉内的阅读器以阻止它干扰发送 EOF 是一种很好的做法(我不知道为什么会这样,我只知道这是这种做法)。

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

任何人都可以提出问题可能是什么或解决方法吗?我已经尝试捕获 Errno::EPIPE 异常和 retrying 但这并不能解决它,重新打开管道(我不完全确定如何做到这一点,因为在分叉发生后很难链接它到主进程),清空块,所以它不做任何工作......仍然没有乐趣。

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

【问题讨论】:

  • 请注意,fork 会返回两次,一次在父项中(返回子项的 pid),一次在子项中(返回 nil)。因此,您应该在条件内调用fork,即:if fork then <parent code> else <child code> endIO.pipe 的文档包含一个示例。
  • @Stefan 谢谢。确实如此,但这不是构建代码的唯一方法,例如this code 与我的非常相似。在我的代码中,作者在 fork 之后立即关闭,不需要 if/else。
  • 你是对的,我从来没有使用过fork的块形式。
  • 当孩子尝试写入管道时,您确定主进程(使fork 调用)存在吗?如果没有任何阅读器,则不能写入管道,反之亦然。例如,您可以通过Process#wait 调用阻止父进程并等待孩子死亡。
  • 你能提供一个minimal reproducible example吗?

标签: ruby pipe fork


【解决方案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 是必不可少的,但在不需要时关闭管道的所有末端肯定更好。

如果这段代码仍然中断,有兴趣看看他们中断了哪些版本的 ruby​​。

【讨论】:

  • 时间久了我都忘记了为什么要问了!我刚刚检查了有问题的库,并使用 MRI v2.6.3 运行了规范,它都是绿色的。我可能不得不重新寻找问题,但在那之前,你可以打勾,因为你看起来是对的,这是一个非常有帮助的推动:)
  • 哈哈,很高兴我帮了忙!感谢您的勾选:D
猜你喜欢
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 2017-04-22
  • 2010-11-08
  • 2014-04-28
  • 2013-04-16
  • 1970-01-01
相关资源
最近更新 更多