由于进程中所有线程共享该进程信号,所以线程库将根据线程掩码决定把信号发送给哪个具体的线程。因此在每个子线程中都单独设置信号掩码,就很容易导致逻辑错误。此外,所有线程共享信号处理函数。也就是说,一个线程中设置了某个信号的信号处理函数后,它将覆盖其他线程为同一个信号设置的信号处理函数。所以应该定义一个专门的线程来处理所有的信号。
(1)在主线程创建出其他子线程之前调用pthread_sigmask来设置好信号掩码,所有新创建的子线程都将自动继承这个信号掩码。这样做之后,实际上所有线程都不会响应被屏蔽的信号了。
(2)在某个线程中调用如下函数来等待信号并处理之:
#include<signal.h>
int sigwait(const sigset_t * set,int *sig);
set参数指定需要等待的信号的集合。参数sig指定的整数用于存储该函数返回的信号值。成功时返回0,失败则返回错误码。
#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) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) static void *sig_thread(void *arg) { printf("yyyyy, thread id is: %ld\n", pthread_self()); sigset_t aset; int s, sig; sigemptyset(&aset); sigaddset(&aset, SIGQUIT); sigaddset(&aset, SIGUSR1); //s = pthread_sigmask(SIG_BLOCK, &aset, NULL); sigset_t *set = (sigset_t *) arg; for (;;) { s = sigwait(set, &sig); if (s != 0) handle_error_en(s, "sigwait"); printf("Signal handling thread got signal %d\n", sig); } } static void handler(int arg) { printf("xxxxx, thread id is: %ld\n", pthread_self()); } int main(int argc, char *argv[]) { pthread_t thread; sigset_t set; int s; /* Block SIGINT; other threads created by main() will inherit * a copy of the signal mask. */ signal(SIGQUIT, handler); // if (s != 0) // handle_error_en(s, "pthread_sigmask"); s = pthread_create(&thread, NULL, &sig_thread, (void *) &set); sigemptyset(&set); sigaddset(&set, SIGQUIT); sigaddset(&set, SIGUSR1); //s = pthread_sigmask(SIG_BLOCK, &set, NULL); if (s != 0) handle_error_en(s, "pthread_create"); printf("sub thread with id: %ld\n", thread); /* Main thread carries on to create other threads and/or do * other work */ pause(); /* Dummy pause so we can test program */ }