Я работаю со следующим примером (который основан на примере в man-странице для pthread_sigmask в linux):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void * silly_worker(void *arg)
{
for(int index=0,max=5; index<max; ++index) {
printf("waiting %d of %d\n",index,max);
sleep(1);
}
puts("Finished waiting. Here comes the SIGSEGV");
strcpy(NULL,"this will crash");
}
static void *
sig_thread(void *arg)
{
sigset_t *set = (sigset_t *) arg;
int s, sig;
for (;;) {
s = sigwait(set, &sig);
if (s != 0)
handle_error_en(s, "sigwait");
printf("Signal handling thread got signal %d\n", sig);
}
}
int
main(int argc, char *argv[])
{
pthread_t thread;
pthread_t thread2;
sigset_t set;
int s;
/* Block SIGINT; other threads created by main() will inherit
a copy of the signal mask. */
sigemptyset(&set);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGSEGV);
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
handle_error_en(s, "pthread_sigmask");
s = pthread_create(&thread, NULL, &sig_thread, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");
/* Main thread carries on to create other threads and/or do
other work */
s = pthread_create(&thread2, NULL, &silly_worker, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");
pause(); /* Dummy pause so we can test program */
}
Согласно man-странице, это должно перехватить SIGSEGV, сгенерированный потоком silly_worker. Но это не так. На самом деле я не уверен, какое агентство получает сигнал вообще. Когда программа запускается, я получаю следующий вывод:
waiting 0 of 5
waiting 1 of 5
waiting 2 of 5
waiting 3 of 5
waiting 4 of 5
Finished waiting. Here comes the SIGSEGV
Segmentation fault
Вы можете видеть, что обработчик сигнала не выводит строку "Ошибка сегментации", поэтому она должна исходить из обработчика по умолчанию. Если значение по умолчанию, то это как бы портит цель примера - установить обработчик сигнала, захватить сигналы и что-то с ними сделать.
Я могу найти множество примеров обработчиков, но ни один из них не подходит для этой ситуации: ни один из них не демонстрирует поток, который вызывает действительно очевидный SIGSEGV, и перехватывает и сообщает об ошибке в своем пользовательском обработчике.
Остается вопрос: как получить специальный обработчик сигнала для получения сигнала из этого потока SIGSEGV?