Among the TCP communication parties, for the convenience of description, the communication parties are replaced by A and B below.
According to the TCP protocol, if B continues to send data after A closes the connection, B will receive A's RST response. If B continues to send data, the system will send a SIGPIPE signal to inform that the connection has been disconnected and stop sending.
The system's default processing behavior for the SIGPIPE signal is to let process B exit.
The default processing behavior of the operating system for the SIGPIPE signal is very unfriendly, let us analyze it.
TCP communication is a full-duplex channel, which is equivalent to two simplex channels, and each end of the connection is responsible for one.
When the peer "closes", although the intention is to close the entire two channels, the local end only receives the FIN packet.
According to the provisions of the TCP protocol, when one end closes the one-way channel it is responsible for, it can still receive data but no longer send data.
In other words, due to the limitations of the TCP protocol, the communicating party cannot know whether the peer's socket has called close or shutdown.
int shutdown(int socket, int how);
The parameter "how" of the shutdown function can be set to close SHUT_RD, SHUT_WR or SHUT_RDWR, which is used to indicate closing the receiving and sending individual channels or closing the sending and receiving channels at the same time.
Call the read/recv method on a socket that has received a FIN packet. If the receiving buffer is empty, 0 is returned, which is often said to indicate that the connection is closed. However, when the write/send method is called for the first time, if there is no problem with the sending buffer, correct writing will be returned (that is, the return value of the write/send function is greater than 0), but the message sent will cause the peer to respond with an RST message. Because the last time the program called write/send, it was normal. When trying to call the write/send function again, the SIGPIPE signal was generated, causing the process to exit.
This default behavior is for us to develop programs, especially for back-end services, which need to serve many clients at the same time. The entire process cannot exit and cannot continue to serve other clients because there is a problem with the connection to a certain client. .
In order to avoid this phenomenon, you can capture the SIGPIPE signal and process it or ignore the signal. The code for ignoring the signal is as follows:
signal(SIGPIPE, SIG_IGN);
After this setting, when the write/send method is called for the second time, -1 will be returned, and the errno error code will be set to SIGPIPE, so the program will know that the peer has been closed.
The above is the detailed content of Linux SIGPIPE signal. For more information, please follow other related articles on the PHP Chinese website!