C语言 pthread 中的信号处理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5282099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Signal handling in pthreads
提问by kingsmasher1
I have created a pthread, and installed a signal handler inside that, same way as we do in main( )function. The thread's signal handler is a separate function. Surprisingly, it is not working, that is the thread's signal handler is not able to catch signals.
我创建了一个 pthread,并在其中安装了一个信号处理程序,就像我们在main( )函数中所做的那样。线程的信号处理程序是一个单独的函数。令人惊讶的是,它不起作用,即线程的信号处理程序无法捕获信号。
Here is the code:
这是代码:
#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);
}
Output:
输出:
Segmentation fault (which means the signal is not caught by handler)
分段错误(这意味着信号没有被处理程序捕获)
回答by sam hocevar
There are several problems with your code:
您的代码有几个问题:
ptris not initialised, so all theptr->parts will crash the program- you are calling
pthread_kill()immediately, very likely before the signal handler has been installed, and in a thread (which has unspecified behaviour) - you call
printf()from a signal handler, which is not guaranteed to work (seeman 7 signalfor a list of safe functions)
ptr未初始化,因此所有ptr->部分都会使程序崩溃- 您正在
pthread_kill()立即调用,很可能在安装信号处理程序之前,并且在线程中(具有未指定的行为) - 您
printf()从信号处理程序调用,该处理程序不能保证正常工作(请参阅man 7 signal有关安全功能的列表)
This will work a lot better, though you'd still need proper thread synchronisation, and as stated elsewhere, you should use sigaction():
这将工作得更好,尽管您仍然需要适当的线程同步,并且如其他地方所述,您应该使用sigaction():
#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)
{
write(1, "Caught signal 11\n", 17);
signal(SIGSEGV,sig_func);
}
void func(data *p)
{
fprintf(stderr, "This is from thread function\n");
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 d;
data *ptr = &d;
signal(SIGSEGV,sig_func); // Register signal handler before going multithread
pthread_attr_init(&attr);
pthread_create(&tid,&attr,(void*)func,ptr);
sleep(1); // Leave time for initialisation
pthread_kill(tid,SIGSEGV);
pthread_join(tid,NULL);
fprintf(stderr, "Name:%s\n",ptr->name);
fprintf(stderr, "Age:%d\n",ptr->age);
}
Edit: install sighandler in main thread
编辑:在主线程中安装 sighandler
回答by sarnold
I believe the core of the problem is that signals are delivered to the process as a whole, rather than individual threads. Commonly, a single thread is nominated to handle all signals; all other threads (including the main thread) need to block the signals using pthread_sigmask().
我认为问题的核心是将信号作为一个整体传递给进程,而不是单个线程。通常,指定一个线程来处理所有信号;所有其他线程(包括主线程)需要使用pthread_sigmask().
You can set the mask to block all signals, start your signal-handler-thread, unmask the signals you wish to handle, and then back in the main thread, start all the other threads you need. They will inherit the "block all signals" mask from the main thread.
您可以设置屏蔽以阻止所有信号,启动您的信号处理程序线程,取消屏蔽您希望处理的信号,然后返回主线程,启动您需要的所有其他线程。他们将从主线程继承“阻止所有信号”掩码。
Incidentally, it's time to move away from signal(3)and switch to sigaction(2), which has reliable semantics and is better standardized. (And thus more portable.)
顺便说一句,是时候离开signal(3)并切换到sigaction(2),它具有可靠的语义并且更好地标准化。(因此更便携。)
回答by R.. GitHub STOP HELPING ICE
The one problem with you code that nobody has mentioned yet is that, while signal blocking (and delivery, if you use pthread_killor raise) are per-thread, signal handlers are per-process. This means they're a very bad mechanism for inter-thread communication, especially if your code will ever be used as library code, since it's extremely bad behavior for a library to alter the caller's signal handlers.
你的代码的一个问题是没有人提到过,虽然信号阻塞(和传递,如果你使用pthread_kill或raise)是每个线程的,但信号处理程序是每个进程的。这意味着它们对于线程间通信来说是一种非常糟糕的机制,特别是如果您的代码将被用作库代码,因为库更改调用者的信号处理程序是非常糟糕的行为。
Also note that using signal handlers for communication between threads has sub-optimal performance compared to other methods of thread signaling like condition variables or barriers, because there's at least one additional user-kernel-user transition (when the signal handler returns).
另请注意,与其他线程信号方法(如条件变量或障碍)相比,使用信号处理程序进行线程之间的通信具有次优性能,因为至少有一个额外的用户-内核-用户转换(当信号处理程序返回时)。

