【问题标题】:popen()ed pipe closed from other extreme kills my program从其他极端情况下关闭的 popen()ed 管道会杀死我的程序
【发布时间】:2023-03-22 18:01:01
【问题描述】:

我有一个用FILE *telnet = popen("telnet server", "w" 打开的管道。如果 telnet 一段时间后因为找不到服务器而退出,则管道从另一个极端关闭。

然后我预计会在fprintf(telnet, ...)fflush(telnet) 调用中出现一些错误,但是相反,我的程序突然在fflush(telnet) 处死掉而没有报告错误。这是正常行为吗?为什么会这样?

【问题讨论】:

  • 您的程序是否检查fflush 的返回值并在适当的时候打印错误?如果不是,则无法打印错误消息是“正常行为”。
  • 我检查 fprintf 返回 >= 0。 fflush() 在 telnet 退出之前返回 0,在 telnet 退出后,对 fflush() 的调用根本不返回(我有 printf("c\n"); if (fflush(telnet)) {printf("a\n"); getchar(); return -1;} printf("b\n"); getchar();,并且只有c 被打印);它的作用就像是调用了 exit()。
  • 你收到SIGPIPE了吗?
  • 如果你在管道另一端没有进程读取数据的情况下写入管道,你会得到一个 SIGPIPE 信号让你知道,而 SIGPIPE 的默认行为是退出 (没有核心转储,但有偏见地退出)。您可以将处理程序设置为SIG_IGN,在这种情况下,您的写入操作应该会因错误而失败,而不是终止。或者您可以设置更精细的信号处理。
  • @WilliamPursell 可能。我不处理信号,所以我不知道,但有道理。终端不显示任何内容。

标签: c pipe popen fflush


【解决方案1】:

将(扩展的)cmets 转换为答案。

如果您在管道另一端没有进程读取数据时写入管道,您会收到一个 SIGPIPE 信号让您知道,并且 SIGPIPE 的默认行为是退出(没有核心转储,但带着偏见退出)。

如果您在 shell 中检查退出状态,您应该会看到 $? 为 141(128 + SIGPIPE,通常为 13)。

如果您不介意进程退出,则无需执行任何操作。或者,您可以将 SIGPIPE 的信号处理程序设置为 SIG_IGN,在这种情况下,您的写入操作应该会因错误而失败,而不是终止进程。或者您可以设置更精细的信号处理。

请注意,您需要小心关闭管道中未使用的文件描述符的原因之一是,如果当前进程正在写入管道但管道的读取端打开,它将不会获得 SIGPIPE —但它可能会被阻塞,因为它无法将更多信息写入管道,直到某个进程从管道读取,但唯一可以从管道读取的进程是试图写入它的进程。

【讨论】:

  • 确实是141 :)
猜你喜欢
  • 1970-01-01
  • 2013-08-22
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多