从其他极端关闭的 popen()ed 管道杀死了我的程序
popen()ed pipe closed from other extreme kills my program
我有一个用 FILE *telnet = popen("telnet server", "w"
打开的管道。如果 telnet 在一段时间后因为找不到服务器而退出,管道从另一个极端关闭。
然后我预计在 fprintf(telnet, ...)
或 fflush(telnet)
调用中会出现一些错误,但相反,我的程序突然在 fflush(telnet)
处死掉而没有报告错误。这是正常行为吗?为什么会这样?
将(扩展的)评论转换为答案。
如果在管道的另一端没有进程读取数据时写入管道,您会收到一个 SIGPIPE 信号让您知道,SIGPIPE 的默认行为是退出(无核心转储,但带着偏见退出)。
如果您检查 shell 中的退出状态,您应该看到 $?
是 141(128 + SIGPIPE,通常为 13)。
如果您不介意进程退出,则无需执行任何操作。或者,您可以将 SIGPIPE 的信号处理程序设置为 SIG_IGN
,在这种情况下,您的写入操作应该因错误而失败,而不是终止进程。或者您可以设置更精细的信号处理。
请注意,您需要小心关闭管道中未使用的文件描述符的原因之一是,如果当前进程正在写入管道但同时打开了管道的读取端,则无法获取SIGPIPE — 但它可能会被阻塞,因为在某些进程从管道读取之前它无法向管道写入更多信息,但唯一可以从管道读取的进程是试图写入它的进程。
我有一个用 FILE *telnet = popen("telnet server", "w"
打开的管道。如果 telnet 在一段时间后因为找不到服务器而退出,管道从另一个极端关闭。
然后我预计在 fprintf(telnet, ...)
或 fflush(telnet)
调用中会出现一些错误,但相反,我的程序突然在 fflush(telnet)
处死掉而没有报告错误。这是正常行为吗?为什么会这样?
将(扩展的)评论转换为答案。
如果在管道的另一端没有进程读取数据时写入管道,您会收到一个 SIGPIPE 信号让您知道,SIGPIPE 的默认行为是退出(无核心转储,但带着偏见退出)。
如果您检查 shell 中的退出状态,您应该看到 $?
是 141(128 + SIGPIPE,通常为 13)。
如果您不介意进程退出,则无需执行任何操作。或者,您可以将 SIGPIPE 的信号处理程序设置为 SIG_IGN
,在这种情况下,您的写入操作应该因错误而失败,而不是终止进程。或者您可以设置更精细的信号处理。
请注意,您需要小心关闭管道中未使用的文件描述符的原因之一是,如果当前进程正在写入管道但同时打开了管道的读取端,则无法获取SIGPIPE — 但它可能会被阻塞,因为在某些进程从管道读取之前它无法向管道写入更多信息,但唯一可以从管道读取的进程是试图写入它的进程。