#include #include #include #include #include #include #include #include struct thread { int pid; pthread_t info; struct thread * prev; struct thread * next; }; struct thread * thread_list; pthread_mutex_t thread_list_mutex; void * thread1(void * unused); void install_segv_handler(void); void segfault_handler(int signum); void spawn(void * (*routine)(void *)); int main(void) { int i; struct thread tl; memset((void *)&tl, 0, sizeof(tl)); tl.pid = getpid(); tl.info = pthread_self(); pthread_mutex_lock(&thread_list_mutex); thread_list = &tl; pthread_mutex_unlock(&thread_list_mutex); // install_segv_handler(); spawn(&thread1); printf("Parent PID: %i\n", getpid()); i = 0; for(;;) { printf("main: %i\n", i); sleep(1); i++; } return 0; } void spawn(void * (*routine)(void *)) { struct thread t; /* FIXME: locking should be done here */ memset(&t, 0, sizeof(t)); pthread_mutex_lock(&thread_list_mutex); pthread_create(&(t.info), NULL, routine, NULL); thread_list->next = &t; t.prev = thread_list; thread_list = thread_list->next; } void install_segv_handler(void) { int rc; struct sigaction sa; sa.sa_handler = &segfault_handler; sa.sa_flags = SA_RESTART; rc = sigaction(SIGSEGV, &sa, NULL); if(rc == -1) { err(1, "Could not install segfault handler"); } } void * thread1(void * unused) { int i = 0; char * c = NULL; thread_list->pid = getpid(); pthread_mutex_unlock(&thread_list_mutex); // install_segv_handler(); printf("Child PID: %i\n", getpid()); for(;;) { printf("thread1: %i\n", i); i++; sleep(1); if(i == 3) { (*c) = 1; } } } void segfault_handler(int signum) { struct thread *tp; void *array[10]; size_t size; char **strings; size_t i; tp = thread_list; while(tp->prev != NULL) { printf("Killing PID %i...\n", tp->pid); tp = tp->prev; } kill(getpid(), SIGQUIT); kill(getppid(), SIGQUIT); size = backtrace (array, 10); strings = backtrace_symbols (array, size); printf ("Obtained %d stack frames.\n", size); for (i = 0; i < size; i++) printf ("%s\n", strings[i]); free (strings); exit(0); }