多线程编程信号处理顺序

105 篇文章 2 订阅
15 篇文章 1 订阅

线程可以使用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 

kill -7 ${子线程PID}

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 

kill -7 ${子线程PID}

SIGBUG: sigbus_handler 

子线程中没有响应的信号处理函数,那么系统会统一选用主进程中的信号处理函sig_handler数进行处理


综上所述


Linux内核没有做特殊处理的情况下:

如果子线程中有写了sigwait的处理函数,那么sigwait处理,主线程是sig_handler处理

子线程中没有响应的信号处理函数,那么系统会统一选用主进程中的信号处理函sig_handler数进行处理








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值