blob: f02747c34fd236e5c6af380f5fde4be24f72a49d [file] [log] [blame]
#include "util.h"
static void segv_handler(__attribute__((unused)) int sig,
__attribute__((unused)) siginfo_t* si,
__attribute__((unused)) void* context) {
test_assert(0 && "Should not reach here");
}
static void usr1_handler(__attribute__((unused)) int sig,
__attribute__((unused)) siginfo_t* si,
__attribute__((unused)) void* context) {
ucontext_t* ctx = (ucontext_t*)context;
sigaddset(&ctx->uc_sigmask, SIGSEGV);
return;
}
static void* do_thread(__attribute__((unused)) void* p) {
raise(SIGUSR1); // just a strange way to spell sigprocmask
// Generate SIGSEGV. Can't use raise, because that will be blocked
(*(int*)1) = 0;
test_assert(0 && "Should not reach here!");
return NULL;
}
int main(void) {
pid_t child;
int status;
pthread_t thread;
if ((child = fork()) == 0) {
struct sigaction act;
act.sa_sigaction = segv_handler;
act.sa_flags = SA_ONSTACK | SA_SIGINFO;
sigemptyset(&act.sa_mask);
sigaction(SIGSEGV, &act, NULL);
act.sa_sigaction = usr1_handler;
sigaction(SIGUSR1, &act, NULL);
pthread_create(&thread, NULL, do_thread, NULL);
test_assert(0 == sched_yield());
sleep(1000);
test_assert(0 && "Should not reach here");
return 0;
}
test_assert(child == wait(&status));
test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);
atomic_puts("EXIT-SUCCESS");
return 0;
}