【问题标题】:Check for a broken pipe before trying to write to it? [duplicate]在尝试写入之前检查是否有损坏的管道? [复制]
【发布时间】:2014-12-09 08:14:58
【问题描述】:

是否可以在尝试写入/读取之前检查管道是否损坏,以便我可以跳过它并继续执行程序?

我正在使用while 循环写入从父级到多个子级通信的管道。在循环过程中,几个孩子将关闭。当循环出现并尝试再次写入它们时,我的程序将关闭,因为它被 SIGPIPE 杀死,因为管道已损坏。我知道管道坏了,我给孩子们编程关闭管道并退出(必要)。我仍然想完成循环并继续执行程序。我希望它检查管道是否损坏,如果损坏则跳过它(没有错误输出),然后继续执行程序(其他孩子仍然需要写入)。

那么,有可能吗? c 中的示例会很棒。

这是我所问问题的简单伪代码表示:

int i = 0;

while(i != 5)
{
    if (mypipe[WRITE] is BROKEN)
        //Do Nothing ---Basically Skip

    else if (some condition)
        write(mypipe[WRITE]);

    i++;
}

这个问题与我的previous post 有关,尽管我的问题的上下文不同。您可以在那里查看实际程序的代码。

【问题讨论】:

  • 我认为 pthread 中的一些线程利用率可能会有所帮助。
  • 作为一种解决方法,孩子可以通知父母(通过管道?)他们已经完成,关闭管道是父母的责任。

标签: c linux pipe posix sigpipe


【解决方案1】:

是的,您可以在读写之前使用像poll(2) 这样的多路复用系统调用。这将告诉您在一系列文件描述符中哪些文件描述符是可读的(有 read 的内容)和可写的(可以是 write 的主题),以检查可读性或可写性。

(您可以使用旧的select(2) 多路复用系统调用,但我更喜欢poll,因为C10K problem

请注意,其他线程可能会在您自己的线程之前执行某些操作。

你想要一些event loop。另请参阅 this answer 的相关问题。

【讨论】:

    【解决方案2】:

    您可以设置一个信号处理程序来忽略SIGPIPE,然后写入缓冲区并检查错误代码:

    /* initialization */
    signal(SIGPIPE, SIG_IGN);
    ...
    
    /* try writing to pipe and detect broken pipe */
    ssize_t written = write(mypipe[WRITE], buf, size);
    if (written == -1 && errno == EPIPE)
      ... remove pipe from the list and continue processing
    

    【讨论】:

      【解决方案3】:

      我的程序关闭了,因为它被 SIGPIPE 杀死了

      如果您安装忽略 SIGPIPE 的信号处理程序,您可以更改该行为,这样对管道的 write() 调用会返回错误而不是杀死您的程序:

        signal(SIGPIPE, SIG_IGN);
      

      那你简单检查一下

      ssize_t rc;
      rc = write(...);
      if (rc == -1) {
          if (errno == EPIPE) {
               //it's broken
          }
       //some other error occured.
      }
      

      【讨论】:

      • 这几乎解决了它。使用以下 tweek:if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { //Do Nothing } 现在我的代码通过了损坏的管道。谢谢!
      猜你喜欢
      • 2016-05-24
      • 1970-01-01
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多