Originally Posted by
nts
Brewbuck, you're a genius! That sounds like a great idea. It may even run faster if I parallelise it :-)
Thanks!
The way signals work in POSIX threads means you have to do some trickery to make the SIGSEGV actually kill the proper thread. Without some special code it will simply kill the entire process including all its threads. I wrote up a small example which shows how it might work.
Code:
#include <signal.h>
#include <pthread.h>
#include <stdio.h>
pthread_t thr;
void do_segv(int x);
void *thread_func(void *arg)
{
int *null = NULL;
int x;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
x = *null;
return NULL;
}
void do_segv(int x)
{
pthread_cancel(thr);
}
int main()
{
signal(SIGSEGV, do_segv);
for(;;)
{
pthread_create(&thr, NULL, thread_func, NULL);
pthread_join(thr, NULL);
printf("Thread died\n");
}
}
This loops forever, spawning new threads then waiting for them to die. The thread which is spawned immediately causes a segfault by dereferencing a NULL pointer. This triggers a SIGSEGV, which is delivered to do_segv(). do_segv() calls pthread_cancel() to kill the thread.
In order for cancellation to work as we want here, the two calls to pthread_setcancelstate() and pthread_setcanceltype() are necessary. Otherwise delivery of the cancellation will only occur at a "cancellation point." But we want it to die right away.
Note the need for a global variable which holds the thread handle. This is so the signal handler can access it. It doesn't need to be volatile, since the signal handler doesn't change its value.
There are drawbacks. If some other part of your app throws a SIGSEGV, it will kill the wrong thread. You can probably imagine ways to deal with that.