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
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).
There are several problems with your code:
ptr
is not initialised, so all the ptr->
parts will crash the programpthread_kill()
immediately, very likely before the signal handler has been installed, and in a thread (which has unspecified behaviour)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
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.)