【问题标题】:what if tail fails while reading from pipe如果从管道读取时 tail 失败怎么办
【发布时间】:2011-10-26 04:15:42
【问题描述】:

distinguish stdout from stderr on pipe

因此,与上面的链接相关,我有一个正在执行 tail 的孩子,而父母正在通过 pipe 读取它的输出。

dup2(pipefd[1], STDOUT_FILENO);
dup2(pipefd[1], STDERR_FILENO);

我的问题是,如果 tail 以某种方式失败,我正在读取的管道会发生什么情况?我在stderr 上能得到什么吗? tail 会自行终止吗?或者它可能会挂在那里defunct

【问题讨论】:

  • 由于它们被复制了,我认为关闭一个的孩子也会关闭另一个,导致后续写入另一个失败。父级将获得文件结尾。但我不是 100% 确定。
  • @wberry:实际上,关闭是您可以对复制的文件描述符执行的一件事,并且不会影响它的其他别名。

标签: c unix pipe stderr tail


【解决方案1】:

tail 终止时,内核将向管道上的另一个进程发送SIGPIPE 信号。此信号的默认操作(如果未安装处理程序)是终止进程。

如果不想处理信号,可以忽略父级中的SIGPIPE(这样tail终止时它不会终止),而是检查errno的值是否为@ 987654326@ 在每个read 之后。此外,您必须从父母那里致电waitwaitpid 来收割僵尸孩子。

【讨论】:

  • 谢谢。我只是想了解为什么SIGPIPE 而不是别的。
  • 这是一个古老的、几乎具有历史意义的 Unix 约定,但今天仍在使用。不过,您可以忽略 SIGPIPE 并检查 errno 在父级中的 read 之后是否为 EPIPE
  • SIGPIPE 不会在管道关闭时发送,而是在尝试写入另一端时发送。
【解决方案2】:

读取时不会得到 EPIPE,只有写入才会返回 EPIPE。您将获得 EOF,由 read 返回 0 指示,并且由于您阅读了 stderr,因此您也会收到错误消息(在 EOF 之前)。

进程会变成僵尸进程,可以使用wait/waitpid获取退出状态,如果有错误,退出状态为非零。

【讨论】:

    【解决方案3】:

    如果 tail 失败,管道读取端的任何读取都将返回 EOF。如果 tail 失败,它已经终止,“失败”的定义是它以非零退出状态终止。它将保留在进程表中(即“已失效”),直到父进程等待它。

    但是为什么你让 tail 对 stderr 和 stdout 使用相同的管道?为什么不只做两个管道?看来这会消除区分两个输出流的问题。

    【讨论】:

    • 谢谢,我相信,现在,我什至不需要阅读stderr。如果tail 失败,stdout 将得到EOF,对吗?我无论如何都在为孩子做wait。所以,它会被清理干净。这听起来对吗?
    猜你喜欢
    • 2011-04-26
    • 1970-01-01
    • 2019-02-10
    • 2011-06-14
    • 2012-08-01
    • 1970-01-01
    • 2010-12-31
    • 2016-01-11
    • 1970-01-01
    相关资源
    最近更新 更多