Signal processing in multi-threading

Source: Internet
Author: User
Tags sigint signal signal handler probook

To write servers under Linux, processing signals is unavoidable. The processing of signals in multiple threads and single threads is a bit different. Reference:

Http://maxim.int.ru/bookshelf/PthreadsProgram/htm/r_40.html

http://aboocool.blog.51cto.com/3189391/626675

Under Linux, each process has its own signal mask, which specifies which signal is blocked, which is not blocked, and is usually handled by calling Sigmask. At the same time each process also has its own signal action, which specifies how the signal is to be handled, usually called sigaction.

After using multi-threading, there are some questions:

    1. When the signal occurs, which thread will receive
    2. Does each thread have its own mask and action
    3. Can each thread handle the signal on its own terms?

First, the transmission of the signal is based on the situation:

    • If it is an abnormal signal (such as a program error, such as Sigpipe, SIGEGV), only the thread that generated the exception is received and processed.
    • If the internal signal is generated with Pthread_kill, only the target thread specified in the Pthread_kill parameter is received and processed.
    • If the signal is generated externally using the KILL command, typically a job control signal such as SIGINT, SIGHUP, then all threads are traversed until a thread that does not block the signal is found and then called to process. (typically found from the main thread), note that only one thread can receive it.

Second, each thread has its own separate signal mask, but all threads share the signal action of the process. This means that you can call Pthread_sigmask (not sigmask) in a thread to determine which signals the threads block. However, you cannot call sigaction to specify how a single thread will be processed. If Sigaction is called to process a signal in a thread, the thread that does not block the signal in the process receives the signal in the same way that the signal will be processed. Also, note that the mask of a child thread is inherited from the main path.

The third problem, because signal action shares the problem, already knows not.

Here is an example:

/*threadsig.c*/#include<signal.h>#include<pthread.h>#include<stdio.h>#include<stdlib.h>#include<string.h>voidSighandler (intSigno); void*THR1_FN (void*Arg) {    structsigaction Action; Action.sa_flags=0; Action.sa_handler=Sighandler; Sigaction (SIGINT,&action, NULL); pthread_t Tid=pthread_self (); intRC; printf ("thread 1 with tid:%lu\n", Tid); RC= Sleep ( -); if(RC! =0) printf ("Thread 1 ... interrupted at%d second\n", --RC); printf ("Thread 1 ends\n"); returnNULL;} void*THR2_FN (void*Arg) {    structsigaction Action; pthread_t Tid=pthread_self (); intRC, err; printf ("thread 2 with tid:%lu\n", Tid); Action.sa_flags=0; Action.sa_handler=Sighandler; Err= Sigaction (SIGALRM, &action, NULL); RC= Sleep ( -); if(RC! =0) printf ("Thread 2 ... interrupted at%d second\n", --RC); printf ("Thread 2 ends\n"); returnNULL;} void*THR3_FN (void*Arg) {pthread_t tid=pthread_self ();    sigset_t Mask; intRC, err; printf ("thread 3 with tid%lu\n", Tid); Sigemptyset (&mask);/*Initializing the mask signal set*/Sigaddset (&mask, SIGALRM); Err= Pthread_sigmask (Sig_block, &mask, NULL); if(Err! =0) {printf ("%d,%s/n", RC, Strerror (RC)); returnNULL; } RC= Sleep (Ten); if(RC! =0) printf ("Thread 3 ... interrupted at%d second\n", --RC); Err= Pthread_sigmask (sig_unblock,&mask,null); if(Err! =0) {printf ("unblock%d,%s/n", RC, Strerror (RC)); returnNULL; } RC= Sleep (Ten); if(RC! =0) printf ("Thread 3 ... interrupted at%d second after unblock\n", --RC); printf ("Thread 3 ends\n"); returnNULL; returnNULL;} intMain (void){    intRC, err; pthread_t thr1, THR2, THR3, Thrm=pthread_self (); printf ("thread main with PID%lu\n", THRM); Err= Pthread_create (&thr1, NULL, THR1_FN, NULL); if(Err! =0) {printf ("error in creating pthread:%d\t%s\n", err, strerror (RC)); Exit (1); }      /*Pthread_kill (THR1, SIGALRM); Send a SIGARLM signal to THR1 before THR2 set the signal handler and then the whole process would be terminated*/Err= Pthread_create (&thr2, NULL, THR2_FN, NULL); if(Err! =0) {printf ("error in creating pthread:%d\t%s\n", err, strerror (RC)); Exit (1); } Err= Pthread_create (&thr3, NULL, THR3_FN, NULL); if(Err! =0) {printf ("error in creating pthread:%d\t%s\n", err, strerror (RC)); Exit (1); } Sleep (Ten); //internally generated signals, only the specified thread can receive, so send to all threadsPthread_kill (THR1, SIGALRM);    Pthread_kill (THR2, SIGALRM);    Pthread_kill (THR3, SIGALRM);    Pthread_kill (THR3, SIGALRM);    Pthread_kill (THR3, SIGALRM); Sleep (5);   Pthread_join (THR1, NULL); /*wait for the threads to complete.*/Pthread_join (THR2, NULL);    Pthread_join (THR3, NULL); printf ("Main ends\n"); return 0;} voidSighandler (intSigno) {pthread_t tid=pthread_self (); printf ("thread with Pid:%lu receive signo:%d\n", Tid, Signo); return;}

In the above code, the main thread creates three threads. Thread 1 registers the SIGINT signal (that is, CTRL + C), thread 2 registers SIGALRM, and the line Cheng is blocking SIGALRM first and then unblocking.

After compiling, look at the results of the operation:

[Email protected]:~/code/test$GCC-O threadsig threadsig.c-Pthread[email protected]-hp-probook-4446s:~/code/test$./Threadsig thread main with PID139946922108736Thread2With Tid:139946905396992Thread1With Tid:139946913789696Thread3With tid139946897004288^cthread with pid:139946922108736 receive Signo:2thread with PID:139946913789696Receive Signo: -Thread1... interrupted at4Secondthread1endsthread with PID:139946905396992Receive Signo: -Thread2... interrupted at4Secondthread2ends^cthread with PID:139946922108736Receive Signo:2^cthread with PID:139946922108736Receive Signo:2thread with pid:139946897004288 receive signo:14Thread3endsmain Ends[email protected]-hp-probook-4446s:~/code/test$

In the first line red place, the main thread is sleep, I press CTRL + C, only the main thread received and processed the signal. Indicates that the process starts looking for a thread that does not block the signal from the main path to handle the signal of the job control class.

Since the main thread sleep was interrupted, and then Sigalrm was sent to three threads, thread 1, 2 was forced to wake from sleep and end the process because it did not block the signal. Process 3 is still in sleep.

In the second row of red, thread 3 The first sleep was finally completed, lifting the blocking of the SIGALRM. Immediately received the blocked SIGALRM (sent 3 times, only received once). PS: Please note the difference between blocking and ignoring the signal.

Signal processing in multi-threading

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.