blob: d019ff163cac45de587212ae76a563e4bfc15e45 [file] [log] [blame]
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
#include "util.h"
static int got_sig;
static void handle_sig(__attribute__((unused)) int sig,
__attribute__((unused)) siginfo_t* info,
__attribute__((unused)) void* mcontext) {
got_sig = 1;
}
static void* do_thread(__attribute__((unused)) void* p) {
sigset_t sigs;
sigemptyset(&sigs);
pthread_sigmask(SIG_SETMASK, &sigs, NULL);
return NULL;
}
int main(void) {
pthread_t thread;
struct sigaction sa;
struct sigevent sevp;
timer_t id;
sigset_t new_mask;
uint64_t sigset = (uint64_t)1 << (SIGUSR1 - 1);
struct itimerspec timeout = { { 0, 0 }, { 0, 1000000 } };
struct syscall_info sigprocmask_syscall = {
SYS_rt_sigprocmask, { SIG_BLOCK, (long)&sigset, 0, 8, 0, 0 }
};
SyscallWrapper delayed_syscall = get_delayed_syscall();
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handle_sig;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
sevp.sigev_notify = SIGEV_SIGNAL;
sevp.sigev_signo = SIGUSR1;
test_assert(0 == timer_create(CLOCK_MONOTONIC, &sevp, &id));
test_assert(0 == timer_settime(id, 0, &timeout, NULL));
delayed_syscall(&sigprocmask_syscall);
test_assert(0 == sigprocmask(SIG_BLOCK, NULL, &new_mask));
test_assert(sigismember(&new_mask, SIGUSR1));
while (1) {
struct itimerspec curr;
test_assert(0 == timer_gettime(id, &curr));
if (curr.it_value.tv_sec == 0 && curr.it_value.tv_nsec == 0) {
break;
}
sleep(1);
}
/**
* The signal might have been delivered after the sigprocmask due to
* scheduling vagaries. If so, create a thread to receive the signal.
* The rr bug we're testing for is that the signal is stashed before
* the sigprocmask and can only be delivered to the main thread, but
* never is.
*/
pthread_create(&thread, NULL, do_thread, NULL);
pthread_join(thread, NULL);
test_assert(got_sig);
atomic_puts("EXIT-SUCCESS");
return 0;
}