Signal handling in pthreads

此生再无相见时 提交于 2019-12-17 07:13:48

问题


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.

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)


回答1:


There are several problems with your code:

  • ptr is not initialised, so all the ptr-> 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 (see man 7 signal for a list of safe functions)

This will work a lot better, though you'd still need proper thread synchronisation, and as stated elsewhere, you should use 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




回答2:


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().

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.)




回答3:


The one problem with you code that nobody has mentioned yet is that, while signal blocking (and delivery, if you use pthread_kill or 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.

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).



来源:https://stackoverflow.com/questions/5282099/signal-handling-in-pthreads

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!