pthreads中的信号处理

时间:2011-03-12 11:03:21

标签: c pthreads signals

我已经创建了一个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);
}

输出:

  

分段错误(这意味着信号不会被处理程序捕获)

3 个答案:

答案 0 :(得分:26)

您的代码存在一些问题:

  • ptr未初始化,因此所有ptr->部分都会导致程序崩溃
  • 您在安装信号处理程序之前,很可能立即调用pthread_kill(),并且在一个线程中(具有未指定的行为)
  • 您从信号处理程序调用{​​{1}},但不保证可以正常工作(请参阅printf()以获取安全功能列表)

虽然你仍然需要正确的线程同步,但是如其他地方所述,你应该使用man 7 signal

sigaction()

编辑:在主线程中安装sighandler

答案 1 :(得分:10)

我认为问题的核心是信号作为一个整体传递给流程,而不是单个线程。通常,提名单个线程来处理所有信号;所有其他线程(包括主线程)需要block the signals using pthread_sigmask()

您可以设置掩码以阻止所有信号,启动信号处理程序线程,取消屏蔽您希望处理的信号,然后返回主线程,启动您需要的所有其他线程。他们将继承主线程中的“阻止所有信号”掩码。

顺便说一下,是时候离开signal(3)并切换到sigaction(2),它具有可靠的语义并且更加标准化。 (因此更便携。)

答案 2 :(得分:4)

你没有提到的代码的一个问题是,虽然信号阻塞(和交付,如果你使用pthread_killraise)是每个线程,信号处理程序是每个进程。这意味着它们是用于线程间通信的非常糟糕的机制,特别是如果您的代码将被用作库代码,因为对于库来说改变调用者的信号处理程序是非常糟糕的行为。

另请注意,与其他线程信号方法(如条件变量或障碍)相比,使用信号处理程序进行线程间通信具有次优性能,因为至少有一个额外的用户 - 内核 - 用户转换(当信号处理程序返回时)