线程可以使用sigwait来对信号进行处理。
但是如果主线程中已经用sig_handler注册了处理函数,子线程里同时也用sigwait来处理信号,那么谁会先处理呢?APUE上只是写了一下依赖于操作系统,这里我们来做实验,看看linux中哪个会处理。
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int quitflag;
sigset_t mask;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t wait = PTHREAD_COND_INITIALIZER;
void * thr_fn(void * arg){
#if 1
int err, signo;
sigset_t oldmask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGBUS);
if((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0){
printf("SIGBLOCK error\n");
exit(err);
}
for(;;){
err = sigwait(&mask, &signo);
if(0 != err){
printf("sigwait failed\n");
exit(err);
}
switch(signo){
case SIGBUS:
printf("SIGBUS\n");
break;
default:
printf("unexpected signal %d\n",signo);
exit(1);
}
}
out0:
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){
printf("SIG_SETMASK error\n");
exit(err);
}
#endif
exit(0);
}
static void sigbus_handler(void* data)
{
printf("SIGBUG: sigbus_handler \n");
return;
}
static void qemu_init_sigbus(void)
{
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
sigaction(SIGBUS, &action, NULL);
}
int main(void){
int err;
pthread_t tid;
qemu_init_sigbus();
err = pthread_create(&tid,NULL,thr_fn,0);
if(err != 0){
printf("can not create thread\n");
exit(err);
}
exit(0);
}
编译代码
gcc test.c -o test -lpthread
运行结果
./test
kill -7 ${主线程PID}
SIGBUG: sigbus_handler
SIGBUG
从而可以看到,如果子线程中有写了sigwait的处理函数,那么sigwait处理,主线程是sig_handler处理
在做个试验
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int quitflag;
sigset_t mask;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t wait = PTHREAD_COND_INITIALIZER;
void * thr_fn(void * arg){
for(;;){
sleep(5);
}
exit(0);
}
#if 1
static void sigbus_handler(void* data)
{
printf("SIGBUG: sigbus_handler \n");
return;
}
static void qemu_init_sigbus(void)
{
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
sigaction(SIGBUS, &action, NULL);
}
#endif
int main(void){
int err;
pthread_t tid;
qemu_init_sigbus();
err = pthread_create(&tid,NULL,thr_fn,0);
if(err != 0){
printf("can not create thread\n");
exit(err);
}
pthread_mutex_lock(&lock);
while(quitflag == 0){
pthread_cond_wait(&wait, &lock);
}
pthread_mutex_unlock(&lock);
quitflag = 0;
exit(0);
}
运行结果
./test
kill -7 ${主线程PID}
SIGBUG: sigbus_handler
SIGBUG: sigbus_handler
子线程中没有响应的信号处理函数,那么系统会统一选用主进程中的信号处理函sig_handler数进行处理
综上所述
Linux内核没有做特殊处理的情况下:
如果子线程中有写了sigwait的处理函数,那么sigwait处理,主线程是sig_handler处理
子线程中没有响应的信号处理函数,那么系统会统一选用主进程中的信号处理函sig_handler数进行处理