SIGSEGV がうまくハンドルできない は代替スタックを指定すべきだったことを id:kazuhooku に教えてもらった。
こうしておけばスタックオーバーフローでも正しくシグナルハンドラが呼ばれる。
man sigaltstack にある例の通り。
stack_t ss;
ss.ss_sp = GC_malloc(SIGSTKSZ);
if (ss.ss_sp == NULL) {
fprintf(stderr, "setSignalHandler malloc failed\n");
exit(-1);
}
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1) {
fprintf(stderr, "setSignalHandler sigaltstack failed\n");
exit(-1);
}
struct sigaction sa;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = signal_handler;
if (sigaction(SIGSEGV, &sa, NULL) != 0 ||
sigaction(SIGTRAP, &sa, NULL) != 0 ||
sigaction(SIGBUS, &sa, NULL) != 0 ||
sigaction(SIGILL, &sa, NULL) != 0) {
fprintf(stderr, "setSignalHandler sigaction failed\n");
exit(-1);
}