如何防止 SIGPIPE(或正确处理它们)

问题描述:

我有一个小型服务器程序,它接受 TCP 或本地 UNIX 套接字上的连接,读取一个简单的命令并(取决于命令)发送回复.

I have a small server program that accepts connections on a TCP or local UNIX socket, reads a simple command and (depending on the command) sends a reply.

问题是客户端可能对答案不感兴趣,有时会提前退出.因此,写入该套接字将导致 SIGPIPE 并使我的服务器崩溃.

The problem is that the client may have no interest in the answer and sometimes exits early. So writing to that socket will cause a SIGPIPE and make my server crash.

防止此处崩溃的最佳做法是什么?有没有办法检查线路的另一边是否仍在阅读?(select() 在这里似乎不起作用,因为它总是说套接字是可写的).或者我应该使用处理程序捕获 SIGPIPE 并忽略它?

What's the best practice to prevent the crash here? Is there a way to check if the other side of the line is still reading? (select() doesn't seem to work here as it always says the socket is writable). Or should I just catch the SIGPIPE with a handler and ignore it?

您通常希望忽略 SIGPIPE 并直接在代码中处理错误.这是因为 C 中的信号处理程序对它们可以做什么有很多限制.

You generally want to ignore the SIGPIPE and handle the error directly in your code. This is because signal handlers in C have many restrictions on what they can do.

最便携的方法是将 SIGPIPE 处理程序设置为 SIG_IGN.这将防止任何套接字或管道写入导致 SIGPIPE 信号.

The most portable way to do this is to set the SIGPIPE handler to SIG_IGN. This will prevent any socket or pipe write from causing a SIGPIPE signal.

要忽略 SIGPIPE 信号,请使用以下代码:

To ignore the SIGPIPE signal, use the following code:

signal(SIGPIPE, SIG_IGN);

如果您使用 send() 调用,另一种选择是使用 MSG_NOSIGNAL 选项,这将改变 SIGPIPE 行为按呼叫关闭.请注意,并非所有操作系统都支持 MSG_NOSIGNAL 标志.

If you're using the send() call, another option is to use the MSG_NOSIGNAL option, which will turn the SIGPIPE behavior off on a per call basis. Note that not all operating systems support the MSG_NOSIGNAL flag.

最后,您可能还需要考虑在某些操作系统上可以使用 setsockopt() 设置的 SO_SIGNOPIPE 套接字标志.这将防止 SIGPIPE 由仅写入它设置的套接字引起.

Lastly, you may also want to consider the SO_SIGNOPIPE socket flag that can be set with setsockopt() on some operating systems. This will prevent SIGPIPE from being caused by writes just to the sockets it is set on.