The
Use of signaling mechanisms in multiple threads of Linux is fundamentally different from the use of signaling mechanisms in processes. In the process environment, the signal processing is to register the signal processing function, when the signal occurs asynchronously, call the processing function to process the signal. It is completely asynchronous (we do not know at all that the signal will come at that point in the process.) )。 However, there are many limitations to the implementation of the signal processing function, such as some functions can not be called in the signal processing functions, and some functions such as read, recv and other calls will be interrupted by the asynchronous signal (interrupt), So we have to deal with situations where these functions are interrupted by a signal when they are called (whether the Enno equals eintr when the function returns).
But the principle of processing signals in multiple threads is completely different, and its basic principle is to convert the signal to asynchronous processing, to synchronize , that is, to use a thread specifically to "wait for" the arrival of the signal, while the other threads can not be completely interrupted by the signal Interrupted (interrupt). This simplifies the processing of signals in a multithreaded environment to a considerable extent. It can also ensure that other threads are not affected by the signal. This allows us to fully predict the signal because it is no longer asynchronous, but rather synchronous (we know exactly which point the signal is going to be processed in which thread). )。 Synchronous programming patterns are always simpler than asynchronous programming patterns. In fact, multithreading compared to multiple processes is one of the advantages: multithreading can be asynchronous in the process of converting things into a synchronized to deal with.
1. sigwait function:
Sigwait-wait for a signal
#include <signal.h>
int sigwait (const sigset_t *set, int *sig);
Description the
sigwait () function suspends execution of the calling thread until the delivery of one of the
Signa LS specified in the signal set set. The function accepts the signal (removes
it from the pending list of signals), and returns the signal number in sig.
the operation of Sigwait () is the same as Sigwaitinfo (2), except that:
* sigwait () only returns the signal number, Rather than a siginfo_t structure describing the signal
.
* The return values of the two functions are different.
Return Value
on success, sigwait () returns 0. On error, it returns a positive error number.
From the description of the man sigwait above, we know that sigwait is
SyncWait for the signal to arrive, rather than the asynchronous waiting signal as it is in the process. The sigwait function uses a signal set as his parameter and returns the signal value when any one of the signals in the collection occurs, unblocking, and then processing the signal accordingly.
2. Remember:In multithreaded code, you always use functions like sigwait or Sigwaitinfo or sigtimedwait to process the signal. Instead of signal or sigaction functions. Because functions such as calling signal or sigaction in one thread will change the signal processing function in the thread. Instead of just changing the signal processing function of the thread that invoked signal/sigaction.
3. Pthread_sigmask function:Each thread has its own set of signal masks (the signal mask), which can be used to mask the response of a thread to certain signals, leaving only the thread that needs to handle the signal to handle the specified signal. \ pthread_sigmask Implemented by using the inheritance relationship of the thread-signal mask set (after the Sigmask is set in the main process, the thread created by the main process inherits the main process's mask)
Pthread_sigmask-examine and change mask of blocked signals #include <signal.h> int pthread_sigmask (int how, const
sigset_t *set, sigset_t *oldset);
Compile and Link with-pthread. DESCRIPTION the Pthread_sigmask () function is just like sigprocmask (2), with the difference, it use in multithreaded
Programs is explicitly specified by posix.1-2001.
The other differences are noted in the this page.
For a description of the arguments and operation's this function, in the Sigprocmask (2). Return VALUE on Success, Pthread_sigmask () returns 0;
On error, it returns an error number.
NOTES A new thread inherits a copy of its creator ' s signal mask.
(From Mans Sigprocmask:)
The behavior of the call are dependent on the value of how, as follows.
Sig_block the set of blocked signals is the union of the current set and the set argument. Sig_unblock the signals in set are removed from the current set of blocked signals.
It is permissible to attempt to unblock a signal which are not blocked. Sig_setMASK the set of blocked signals is set to the argument set.
If Oldset is Non-null, the previous value of the signal mask was stored in Oldset. If set is NULL, then the signal mask are unchanged (i.e., how are ignored), but the current value of the signal mask is Nev Ertheless returned in Oldset (if it isn't NULL).
4. Pthread_kill function:In a multithreaded program, a thread can use Pthread_kill to send a signal to a thread (including itself) that is specified in the same process. Note that you typically do not use the Kill function in multiple threads to send a signal, because kill is a signal to the process, and the result is that the running thread handles the signal, and if the thread does not register a signal handler, it causes the entire process to exit.
#include <signal.h>
int pthread_kill (pthread_t thread, int sig);
Compile and link with-pthread.
DESCRIPTION
the Pthread_kill () function sends the signal SIG to thread, another thread in the same
process as the Caller. The signal is asynchronously directed to thread.
If Sig is 0, then no signal are sent, but error checking is still performed; This can is
used to check for the existence of a thread ID.
Return VALUE in
success, Pthread_kill () returns 0; On error, it returns a error number, and no signal is
sent.
errors
esrch No thread with the ID thread could to be found.
Einval an invalid signal is specified.
5. Remember:The signal that calls the sigwait synchronous wait must be masked in the calling thread and should normally be masked in all threads (this ensures that the signal will never be sent to any other thread other than the call to Sigwait), which is achieved by using the inheritance relationship of the signal mask. (The semantics of sigwait require that all threads (including the thread calling sigwait) have the signal masked, for re Liable operation. Otherwise, a signal that arrives not blocked in sigwait
might be delivered to another thread.)
6. code example:(from Mans Pthread_sigmask)
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include < signal.h> #include <errno.h>/* Simple error handling functions * * #define HANDLE_ERROR_EN (en, msg) \ D o {errno = en; perror (msg); exit (exit_failure); while (0) static void * Sig_thread (void *arg) {sigset_t *set =
(sigset_t *) arg;
int S, SIG; for (;;)
{s = sigwait (set, &sig);
if (S!= 0) handle_error_en (S, "sigwait");
printf ("Signal handling thread got Signal%d\n", SIG);
int main (int argc, char *argv[]) {pthread_t thread;
sigset_t set;
int s; /* block SIGINT;
The other threads created by main () is inherit a copy of the signal mask.
* * Sigemptyset (&set);
Sigaddset (&set, sigquit);
Sigaddset (&set, SIGUSR1);
s = Pthread_sigmask (Sig_block, &set, NULL);
if (S!= 0) Handle_error_en (S, "pthread_sigmask");
s = pthread_create (&thread, NULL, &sig_thread, (void *) &set);
if (S!= 0) handle_error_en (S, "pthread_create"); /* Main thread carries on to create other threads and/or does other work * * pause ();
/* Dummy Pause so we can test program * * return 0; }
Compile-run Status:
digdeep@ubuntu:~/pthread/learnthread$ Gcc-wall-pthread-o Pthread_sigmask pthread_sigmask.c
digdeep@ubuntu:~/pthread/learnthread$./pthread_sigmask &
[1] 4170
digdeep@ubuntu:~/pthread/learnthread$ kill-quit%1
digdeep@ubuntu:~/pthread/learnthread$ Signal handling thread got Signal 3
digdeep@ubuntu:~/pthread/learnthread$ KILL-USR1%1
digdeep@ubuntu:~/pthread/learnthread$ Signal handling thread got Signal 10
digdeep@ubuntu:~/pthread/learnthread$ kill-term%1
digdeep@ubuntu:~/pthread/learnthread$
[1]+ terminated./pthread_sigmask
Digdeep@ubuntu:~/pthread/learnthread$ This example demonstrates that by blocking some signals in the main thread, the other threads inherit the signal mask and then use the Sigwait function to synchronize the signal with a single thread. So that other threads are not affected by the signal.