The server shut down the client socket_fd that is being connected, and the response process made by the client
When the server closes a connection, if the client sends data. According to the TCP protocol, an rst response is received. When the client sends data to the server, the system sends a sigpipe signal to the process, telling the process that the connection has been disconnected, do not write any more. According to the default signal processing rules, the default operation of the sigpipe signal is terminate (termination, exit), so the client will exit. If you do not want the client to exit, set sigpipe to sig_ign, for example, signal (sigpipe, sig_ign). At this time, sigpipe is handed over to the system for processing. If fork is adopted on the server, garbage collection should be performed to prevent the generation of zombie processes. This can be done in this way: Signal (sigchld, sig_ign); handed over to the system init for recovery.
Here, sub-processes will not generate zombie processes.
========================================================== ========================================================
What is caused by sigpipe?ProgramExit
Collect online information for reference:
Http://blog.chinaunix.net/u2/69143/showart_1087349.html
When the server closes a connection, if the client sends data. According to the TCP protocol, an rst response is received. When the client sends data to the server, the system sends a sigpipe signal to the process, telling the process that the connection has been disconnected, do not write any more.
According to the default signal processing rules, the default operation of the sigpipe signal is terminate (termination, exit), so the client will exit. If you do not want the client to exit, set sigpipe to sig_ign.
For example, signal (sigpipe, sig_ign );
At this time, sigpipe is handed over to the system for processing.
If fork is used on the server, it is necessary to collect the garbage process to prevent the generation of the zombie process. You can handle it like this:
Signal (sigchld, sig_ign); hand it to the system init for recycling.
Here, sub-processes will not generate zombie processes.
Http://www.cublog.cn/u/31357/showart_242605.html
I haven't done c development for a long time, and recently I have been focusing on old business.
I heard that the data size of the sender and receiver is inconsistent when the socket development of another project team encounters problems. We recommend that you use the re-transmission mechanism of writen to avoid signal interruption errors. There is still a problem after adoption. PM asked me to help with the research.
UNP has been around for a long time and has never been used for underlying development, nor has it been used for UNP vol1 at hand. So I did a test program to study the actual situation.
Test environment: as3 and RedHat 9 (no NC by default)
First download the UNP source code:
Wget http://www.unpbook.com/unpv13e.tar.gz
Tar xzvf * .tar.gz;
Configure; Make Lib.
Then refer to str_cli.c and tcpcli01.c and write the testCodeClient. c
# Include "unp. H"
# Define maxbuckets 40960
Void processsignal (INT signo)
{
Printf ("signal is % d/N", signo );
Signal (signo, processsignal );
}
Void
Str_cli (File * FP, int sockfd)
{
Char sendline [maxbuf], recvline [maxbuf];
While (1 ){
Memset (sendline, 'A', sizeof (sendline ));
Printf ("begin send % d Data/N", maxbuf );
Writen (sockfd, sendline, sizeof (sendline ));
Sleep (5 );
}
}
Int
Main (INT argc, char ** argv)
{
Int sockfd;
Struct sockaddr_in servaddr;
Signal (sigpipe, sig_ign );
// Signal (sigpipe, processsignal );
If (argc! = 2)
Err_quit ("Usage: tcpcli [port]");
Sockfd = socket (af_inet, sock_stream, 0 );
Bzero (& servaddr, sizeof (servaddr ));
Servaddr. sin_family = af_inet;
Servaddr. sin_port = htons (atoi (argv [1]);
Inet_ton (af_inet, "127.0.0.1", & servaddr. sin_addr );
Connect (sockfd, (Sa *) & servaddr, sizeof (servaddr ));
Str_cli (stdin, sockfd);/* do it all */
Exit (0 );
}
To facilitate the observation of error output, lib/writen. C has also been modified and some logs are added:
/* Include writen */
# Include "unp. H"
Ssize_t/* write "N" bytes to a descriptor .*/
Writen (int fd, const void * vptr, size_t N)
{
Size_t nleft;
Ssize_t nwritten;
Const char * PTR;
PTR = vptr;
Nleft = N;
While (nleft> 0 ){
Printf ("begin writen % d/N", nleft );
If (nwritten = write (FD, PTR, nleft) = 0 ){
If (nwritten 0 & errno = eintr ){
Printf ("intterupt/N ");
Nwritten = 0;/* and call write () Again */
}
Else
Return (-1);/* Error */
}
Nleft-= nwritten;
PTR + = nwritten;
Printf ("already write % d, left % d, errno = % d/N", nwritten, nleft, errno );
}
Return (N );
}
/* End writen */
Void
Writen (int fd, void * PTR, size_t nbytes)
{
If (writen (FD, PTR, nbytes )! = Nbytes)
Err_sys ("writen error ");
}
Put client. c In the tcpclieserv directory, modify the makefile, and add the compilation target of client. C.
Client: client. c
$ {CC }$ {cflags}-o $ {libs}
Then you can start the test.
Test 1 ignores the sigpipe signal. Before writen, the recipient closes the acceptance process.
Local Server:
NC-l-P 30000
Local client:
./Client 30000
Begin send 40960 data
Begin writen 40960
Already write 40960, left 0, errno = 0
Begin send 40960 data
Begin writen 40960
Already write 40960, left 0, errno = 0
After the server is stopped in the previous step, the client will continue to display:
Begin send 40960 data
Begin writen 40960
Writen error: broken pipe (32)
Conclusion: Before the write operation, the socket of the other party is interrupted. The sending end will return-1, and the errno number is epipe (32)
Test 2 catch sigpipe signal. Before writen, the recipient closes the acceptance process.
Modify the client code and catch the sigpipe signal.
// Signal (sigpipe, sig_ign );
Signal (sigpipe, processsignal );
Local Server:
NC-l-P 30000
Local client:
Make Client
./Client 30000
Begin send 40960 data
Begin writen 40960
Already write 40960, left 0, errno = 0
Begin send 40960 data
Begin writen 40960
Already write 40960, left 0, errno = 0
After the server is stopped in the previous step, the client will continue to display:
Begin send 40960 data
Begin writen 40960
Signal is 13
Writen error: broken pipe (32)
Conclusion: Before write, the socket of the other party is interrupted. When the sender writes the data, the sigpipe response function is called first, and then the write returns-1, and the errno number is epipe (32)
Test 3: The recipient closes the acceptance process during the writen process.
To facilitate the operation, increase the volume of data written once, and change maxbuf to 4096000
Local Server:
NC-l-P 30000
Local client:
Make Client
./Client 30000
Begin send 4096000 data
Begin writen 4096000
After the server is stopped in the previous step, the client will continue to display:
Already write 589821, left 3506179, errno = 0
Begin writen 3506179
Writen error: Connection reset by peer (104)
Conclusion: In socket write, the other party's socket is interrupted. the sender's write will first return the number of bytes that have been sent, and-1 will be returned when the second write operation is performed. errno is econnreset (104)
Why are the results different when the sender writes the socket again after the other party has interrupted the test. From the unp5.12 and 5.13 found later, you can find the answer.
The client's call to Readline may happen before the server's rst is already ed by the client, or it may happen after. if the Readline happens before the RST is already ed, as we 've shown in our example, the result is an unexpected EOF in the client. but if the RST arrives first, the result is an econnreset ("Connection reset by peer") Error return from Readline.
The above explains the symptom of Test 3. When writing, the RST is received.
What happens if the client ignores the error return from Readline and writes more data to the server? This can happen, for example, if the client needs to perform two writes to the server before reading anything back, with the first write eliciting the rst.
The rule that applies is: when a process writes to a socket that has ed an rst, The sigpipe signal is sent to the process. the default action of this signal is to terminate the process, so the process must catch the signal to avoid being involuntarily terminated.
If the process either catches the signal and returns from the signal handler, or ignores the signal, the write operation returns epipe.
The above explains the test 1 and 2. Write a socket that has received the rst, and the system kernel will send the sigpipe to the sending process. If the catch/ignore signal of the process, the write will return the epipe error.
Therefore, it is recommended that the UNP application process the sigpipe signal as needed. At least do not use the default processing method of the system to process the signal. The default processing method of the system is to exit the process, in this way, it is difficult for your application to investigate why the processing process exits.
Http://blog.csdn.net/shcyd/archive/2006/10/28/1354577.aspx
In Unix systems, if the network is disconnected when sending data while waiting for the Protocol to send data, the process that calls sending will receive a sigpipe signal, and the process processes the signal by default is terminated.
In Unix systems, if the network is disconnected when the Recv function is waiting for the Protocol to receive data, the process that calls the Recv will receive a sigpipe signal, and the process processes the signal by default is terminated.
Solution:
Called at Initialization Signal (sigpipe, sig_ign) Ignore this signal (only once)
At that time, the send or Recv function will return-1, errno is epipe, and socket or other processing can be disabled as needed
GDB:
GDB interrupts the program when it receives sigpipe by default. You can call this function. Handle sigpipe nostop print
Related
(1) default actions for sig_dfl signals:
(A) if the default action is to suspend a thread, the thread's execution is temporarily suspended. When the thread is paused, no additional signals sent to the thread are delivered until the thread starts executing, except for sigkill.
(B) Set the signal action of the suspended signal to sig_dfl, and the default action is to ignore the signal (sigchld ).
(2) sig_ign ignores Signals
(A) The delivery of the signal has no effect on the thread.
(B) The system does not allow the operation of the sigkill or sigtop signal to be set to sig_dfl.
(3) pointer to function-capture Signal
(A) Once the signal is delivered, the receiving thread executes the signal capture program on the specified address. After the function is returned after the signal is captured, the receiving thread must resume execution at the breakpoint.
(B) Use the C language function call method to access the signal capturing program:
Void func (signo)
Int signo;
Func () is the specified signal capturing function, and signo is the code of the signal being delivered
(C) If the sigfpe, sigill, or SIGSEGV signal is not generated by the standard-defined kill () or raise () function of C, then from the signal sigfpe, sigill, after the signal capture function of SIGSEGV returns normally, the thread behavior is undefined.
(D) The system does not allow threads to capture sigkill and sigstop signals.
(E) If the thread establishes a signal capture function for the sigchld signal and the thread has a subthread that is not waiting to terminate, it does not specify whether to generate a sigchld signal to specify the subthread.
Each signal is given a symbolic name by oskit. For a 32-bit i386 platform, there are 32 types of signals with 32 characters. The following table provides common symbol names, descriptions, and their signal values.
Whether the description of the symbol name signal value complies with POSIX
Sighup 1 detected hanging up on the control terminal or the control thread died
SIGINT 2 interaction notice signal is
Sigquit 3 interaction stop signal is
Which of the following commands does sigill 4 detect illegal hardware?
Sigtrap 5 does not return from the trap
SIGABRT 6 abnormal termination signal is
Sigemt 7 command no
The incorrect arithmetic operation signal of sigfpe 8 is
Sigkill 9 termination signal is
Sigbus 10 bus error no
SIGSEGV 11 detected that invalid memory call is
Sigsys 12 system call error parameter No
Sigpipe 13 is written in a reader-less Pipeline
When sigalrm 14 is reported, the signal is
Sigterm 15 Termination signal is
Sigurg 16 I/O channel emergency signal No
Sigstop 17 pause signal is
Sigtstp 18 interaction pause signal is
Sigcont 19 if paused, continue to be
Sigchld 20 sub-thread termination or suspension is
A member of the background thread group of sigttin 21 tries to read
Sigttou 22 background thread group members try to write to the control terminal is
Sigio 23 allows I/O signal No
Sigxcpu 24 exceeds CPU limit no
Sigxfsz 25 exceeds the file size limit no
Sigvtalrm 26 virtual time alarm No
Sigprof 27 side time Alert No
Sigwinch 28 window size change no
Siginfo 29 message request no
SIGUSR1 30 reserved as user-defined signal 1 is
Sigusr2 31 is reserved as a user-defined Signal
Note: : The Linux signal mechanism is basically inherited from UNIX systems. In early Unix systems, the signal mechanism was relatively simple and original, and some problems were exposed in practice. Therefore, the signals built on the early mechanism were called "unreliable signals ", signals smaller than sigrtmin (in Red Hat 7.2, sigrtmin = 32, sigrtmax = 63) are unreliable signals. This is the source of "unreliable signal. The main problem is that each time a process processes a signal, it sets the response to the signal as the default action. In some cases, it may lead to incorrect signal processing. Therefore, if you do not want such an operation, you need to call signal () again at the end of the signal processing function (), reinstall the signal.
In addition, I will make some supplements to generate an rst response so that the system sends a sigpipe signal, which can be divided into two situations:
1. The network between the client and the server is disconnected, or the server is powered off, and the physical connection is disconnected. In this case, the client will not exit, and the send function will be executed normally without any errors. Because the physical network is disconnected, the server does not respond to the error message from the client. If there is no rst response, it naturally does not generate a sigpipe signal. However, when the server returns to normal again, the RST response is generated for the messages sent from the client, and the client receives the sigpipe signal and the program exits, however, the send function returns-1. Exception Handling is supported.
2. The client can communicate with the server through the network. If the service program fails, the client program will immediately exit because the server can normally return an error message. When the client receives the message, the sigpipe signal will be generated. However, I am not sure that the RST response is returned by the server at this time. The packet capture result shows that there is no rst flag. The level is limited. Only this is the case.
Reprinted statement:From http://linux.chinaunix.net/techdoc/net/2008/10/10/1037290.shtml (Linux era)