我已经创建了一个pthread,并在其中安装了一个信号处理程序,就像我们在main( )
函数中一样。线程的信号处理程序是一个单独的函数。令人惊讶的是,它无法正常工作,即线程的信号处理程序无法捕获信号。
以下是代码:
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
typedef struct data
{
char name[10];
int age;
}data;
void sig_func(int sig)
{
printf("Caught signal: %d\n",sig);
signal(SIGSEGV,sig_func);
}
void func(data *p)
{
printf("This is from thread function\n");
signal(SIGSEGV,sig_func); // Register signal handler inside thread
strcpy(p->name,"Mr. Linux");
p->age=30;
sleep(2); // Sleep to catch the signal
}
int main()
{
pthread_t tid;
pthread_attr_t attr;
data *ptr;
pthread_attr_init(&attr);
pthread_create(&tid,&attr,(void*)func,ptr);
pthread_kill(tid,SIGSEGV);
pthread_join(tid,NULL);
printf("Name:%s\n",ptr->name);
printf("Age:%d\n",ptr->age);
}
输出:
分段错误(这意味着信号不会被处理程序捕获)
答案 0 :(得分:26)
您的代码存在一些问题:
ptr
未初始化,因此所有ptr->
部分都会导致程序崩溃pthread_kill()
,并且在一个线程中(具有未指定的行为)printf()
以获取安全功能列表)虽然你仍然需要正确的线程同步,但是如其他地方所述,你应该使用man 7 signal
:
sigaction()
编辑:在主线程中安装sighandler
答案 1 :(得分:10)
我认为问题的核心是信号作为一个整体传递给流程,而不是单个线程。通常,提名单个线程来处理所有信号;所有其他线程(包括主线程)需要block the signals using pthread_sigmask()
。
您可以设置掩码以阻止所有信号,启动信号处理程序线程,取消屏蔽您希望处理的信号,然后返回主线程,启动您需要的所有其他线程。他们将继承主线程中的“阻止所有信号”掩码。
顺便说一下,是时候离开signal(3)
并切换到sigaction(2)
,它具有可靠的语义并且更加标准化。 (因此更便携。)
答案 2 :(得分:4)
你没有提到的代码的一个问题是,虽然信号阻塞(和交付,如果你使用pthread_kill
或raise
)是每个线程,信号处理程序是每个进程。这意味着它们是用于线程间通信的非常糟糕的机制,特别是如果您的代码将被用作库代码,因为对于库来说改变调用者的信号处理程序是非常糟糕的行为。
另请注意,与其他线程信号方法(如条件变量或障碍)相比,使用信号处理程序进行线程间通信具有次优性能,因为至少有一个额外的用户 - 内核 - 用户转换(当信号处理程序返回时)