通常,而不是抓住SIGPIPE
一个忽略它,这会导致write
失败EPIPE
而不是静默终止您的程序。
但是:如果您SIGPIPE
在写入管道时遇到错误,请不要再试一次。它永远不会起作用。 SIGPIPE
意味着管道没有阅读器——如果管道现在没有阅读器,它将永远不会有阅读器。(这样想:没有阅读器的管道怎么会有一个?这是不可能的!)
您的问题是您正在关闭管道的另一端。解决这个问题,不要担心SIGPIPE
。 SIGPIPE
只是症状。
编辑:这里有两个问题需要回答。如果你不能回答这两个问题,那就不要费心处理SIGPIPE
.
什么会导致我的程序收到SIGPIPE
? 接收的唯一方法SIGPIPE
是关闭管道的读取端。如果读取过程崩溃,或者它被编程为关闭管道,就会发生这种情况。如果您正在编写网络服务器,或与未知进程通信,这可能很常见。但是,如果您编写的两个程序都在本地运行,那么它可能表示编程错误。
我的程序捕获时会做什么SIGPIPE
? 如果您正在编写一个使用管道与服务器通信的客户端进程,那么您应该如何处理SIGPIPE
?您无法重试,客户端通常无法重新启动它们所连接的服务器。只需做明智的默认事情,然后SIGPIPE
终止您的程序。但是,如果服务器正在向它控制和获取的客户端发送数据SIGPIPE
,它可能会重新启动客户端。但这可能是一个非常糟糕的主意——例如,如果客户端是确定性的,它只会再次崩溃,您最终会陷入无限循环而不是简单的崩溃。
所以这里的一般格言是“只捕获你准备处理的错误。 ”不要仅仅为了完整性而捕获错误。只要让他们让你的程序崩溃,或者导致操作失败,你就可以稍后回去调试它。
代码片段:这是我的一个项目的代码片段。如果你运行它,SIGPIPE
不会终止你的进程。相反,write
会产生EPIPE
错误。如果您正在编写网络服务器,那么EPIPE
客户端可能会突然断开连接的一种可能方式。
void
ignore_sigpipe(void)
{
struct sigaction act;
int r;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
act.sa_flags = SA_RESTART;
r = sigaction(SIGPIPE, &act, NULL);
if (r)
err(1, "sigaction");
}