Search code examples
cpthreadssignals

Signal handling in pthreads


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>
#include <string.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)


Solution

  • 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>
    #include <string.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