#include <signal.h>
int pthread_sigmask(int how, const sigset_t *restrict set,
                    sigset_t *restrict oset);
                                                                      Returns: 0 if OK, error number on failure
说明:
1. 每个线程都有自己独立的信号屏蔽,但却共享进程的信号处理。这意味着在一个线程中改变信号处理,会影响到其他线程。
2. 创建新线程时,新线程继承主线程的当前信号屏蔽。
3. 当信号是由于硬件错误或者定时器溢出而引起时,信号被发往引起该信号的线程;其他情况下,信号送往进程的随意一个线程。
4. pthread_sigmask 是多线程下的信号屏蔽设置函数,参数与 sigprocmask 类似。后者在多线程环境下,行为未定义。
#include <signal.h>
int sigwait(const sigset_t *restrict set, int *restrict signop);
                                                                   Returns: 0 if OK, error number on failure
说明:
1. 使用 sigwait 等待特定信号前,首先要屏蔽该信号,进入sigwait 后会自动解除阻塞,sigwait 返回前,重新恢复信号屏蔽。
2. sigwait 提供了异步信号的同步处理方式—— 可以在每个线程中屏蔽信号,而选特定的一个或多个线程去处理信号。在线程的上下文中处理信号,而不在传统的打断线程执行的信号句柄。
3. 当有多个线程都调用 sigwait 等待同一信号时,信号到达时,只有一个线程的 sigwait 会返回。另外当信号句柄与sigwait 同时存在时,信号的处理取决于实现,但两者只能取其一。
4. APUEv2 给出的例子如下:
#include "apue.h"
#include <pthread.h>
int         quitflag;   /* set nonzero by thread */
sigset_t    mask;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t wait = PTHREAD_COND_INITIALIZER;
void *
thr_fn(void *arg)
{
    int err, signo;
    for (;;) {
        err = sigwait(&mask, &signo);
        if (err != 0)
            err_exit(err, "sigwait failed");
        switch (signo) {
        case SIGINT:
            printf("\ninterrupt\n");
            break;
        case SIGQUIT:
            pthread_mutex_lock(&lock);
            quitflag = 1;
            pthread_mutex_unlock(&lock);
            pthread_cond_signal(&wait);
            return(0);
        default:
            printf("unexpected signal %d\n", signo);
            exit(1);
        }
    }
}
int
main(void)
{
    int         err;
    sigset_t    oldmask;
    pthread_t   tid;
    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGQUIT);
    if ((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0)
        err_exit(err, "SIG_BLOCK error");
    err = pthread_create(&tid, NULL, thr_fn, 0);
    if (err != 0)
        err_exit(err, "can't create thread");
    pthread_mutex_lock(&lock);
    while (quitflag == 0)
        pthread_cond_wait(&wait, &lock);
    pthread_mutex_unlock(&lock);
    /* SIGQUIT has been caught and is now blocked; do whatever */
    quitflag = 0;
    /* reset signal mask which unblocks SIGQUIT */
    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        err_sys("SIG_SETMASK error");
    exit(0);
}
#include <signal.h>
int pthread_kill(pthread_t thread, int signo);
                                                                       Returns: 0 if OK, error number on failure
说明:
1. 该函数用来向线程发送信号。
2. 如果信号默认会终止进程,则向线程发送该信号会终止线程所在的进程。
3. 定时器(alarm_timer)是进程资源,进程的所有线程共享同一套定时器。所以在线程中同时设置定时器会相互干扰。