Refer to this article:
Http://www.cnblogs.com/coding-my-life/p/4782529.html
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:
- When the signal occurs, which thread will receive
- Does each thread have its own mask and action
- 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.
Q: Can each thread handle the signal on its own terms?
The third problem, because signal action shares the problem, already knows not .
Here's 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;}
View Code
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:139946922108736Receive 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:139946897004288Receive Signo: -Thread3endsmain Ends[email protected]-hp-probook-4446s:~/code/test$
View Code
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.
Because the main thread sleep was interrupted and then sent a sigalrm to three threads, thread 1, 2 was forced to wake from sleep and end the thread because it did not block the signal. Thread 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.
That is, the signal that has not been processed is still to be processed after the blocking is lifted. This process of processing the signal from the kernel can also be inferred, because
Data members in the task_struct structure of the process relating to outstanding signals in this process : struct sigpending pending:
struct sigpending{
struct Sigqueue *head, *tail;
sigset_t signal;
};
The inside of the signal is a record of the new Sigalam, and there is always no thread to deal with, and it remains here.
Threading and Signal processing