pthread_sigmask(3THR) does for a thread what sigprocmask(2) does for a process—it sets the thread's signal mask. When a new thread is created, its initial mask is inherited from its creator.
The call to sigprocmask() in a multithreaded process is equivalent to a call to pthread_sigmask(). See the sigprocmask(2) page for more information.
pthread_kill(3THR) is the thread analog of kill(2)—it sends a signal to a specific thread. This, of course, is different from sending a signal to a process. When a signal is sent to a process, the signal can be handled by any thread in the process. A signal sent by pthread_kill() can be handled only by the specified thread.
Note than you can use pthread_kill() to send signals only to threads in the current process. This is because the thread identifier (type thread_t) is local in scope—it is not possible to name a thread in any process but your own.
Note also that the action taken (handler, SIG_DFL, SIG_IGN) on receipt of a signal by the target thread is global, as usual. This means, for example, that if you send SIGXXX to a thread, and the SIGXXX signal disposition for the process is to kill the process, then the whole process is killed when the target thread receives the signal.
For multithreaded programs, sigwait(2) is the preferred interface to use, because it deals well with asynchronously generated signals.
sigwait() causes the calling thread to wait until any signal identified by its set argument is delivered to the thread. While the thread is waiting, signals identified by the set argument are unmasked, but the original mask is restored when the call returns.
All signals identified by the set argument must be blocked on all threads, including the calling thread; otherwise, sigwait() might not work correctly.
Use sigwait() to separate threads from asynchronous signals. You can create one thread that is listening for asynchronous signals while your other threads are created to block any asynchronous signals that might be set to this process.
Two versions of sigwait() are available beginning with the Solaris Operating Environment 2.5 release: the new Solaris Operating Environment 2.5 version, and the POSIX.1c version. New applications and libraries should use the POSIX standard interface, as the Solaris Operating Environment version might not be available in future releases.
The syntax for the two versions of sigwait() is shown below.
#include <signal.h> /* the Solaris 2.5 version*/ int sigwait(sigset_t *set); /* the POSIX.1c version */ int sigwait(const sigset_t *set, int *sig);
When the signal is delivered, the POSIX.1c sigwait() clears the pending signal and places the signal number in sig. Many threads can call sigwait() at the same time, but only one thread returns for each signal that is received.
With sigwait() you can treat asynchronous signals synchronously—a thread that deals with such signals simply calls sigwait() and returns as soon as a signal arrives. By ensuring that all threads (including the caller of sigwait()) have such signals masked, you can be sure that signals are handled only by the intended handler and that they are handled safely.
By always masking all signals in all threads, and just calling sigwait() as necessary, your application will be much safer for threads that depend on signals.
Usually, you create one or more threads that call sigwait() to wait for signals. Because sigwait() can retrieve even masked signals, be sure to block the signals of interest in all other threads so they are not accidentally delivered.
When a signal arrives, a thread returns from sigwait(), handles the signal, and calls sigwait() again to wait for more signals. The signal-handling thread is not restricted to using Async-Signal-Safe functions and can synchronize with other threads in the usual way. (The Async-Signal-Safe category is defined in MT Interface Safety Levels.)