#include #include #include #include #include #include #include static void segv_handler (int sig, siginfo_t *si, void *unused) { _exit (EXIT_SUCCESS); } static void die (const char *msg, int err) { if (err) perror (msg); else fprintf (stderr, "%s\n", msg); abort (); } static void do_expect_signal (void (*fn)(void)) { struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset (&sa.sa_mask); sa.sa_sigaction = segv_handler; if (sigaction (SIGSEGV, &sa, NULL) == -1) die ("sigaction failed", errno); (*fn)(); _exit (EXIT_FAILURE); } static bool expect_signal (void (*fn)(void)) { pid_t pid, wp; int status; pid = fork (); if (pid == -1) die ("fork failed", errno); if (pid == 0) do_expect_signal (fn); /* never returns */ wp = waitpid (pid, &status, 0); if (wp != pid) die ("waitpid did not work", wp == -1 ? errno : 0); if (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_SUCCESS) return true; return false; } static void deref (void) { *((char *)0) = 0; } static bool fault (void) { if (expect_signal(deref)) { printf("Signal OK\n"); return true; } return false; } int main (int argc, char **argv) { bool ok = true; ok = fault(); if (ok) return EXIT_SUCCESS; return EXIT_FAILURE; }