10#include <sys/syscall.h>
15 volatile int entered, done;
18static void finished(
void* argument) {
20 __atomic_store_n(&
waiter->done, 1, __ATOMIC_RELEASE);
22static void* wait_for_signal(
void* argument) {
24 pthread_cleanup_push(finished,
waiter);
25 __atomic_store_n(&
waiter->entered, 1, __ATOMIC_RELEASE);
27 pthread_cleanup_pop(1);
30static volatile int handled;
31static siginfo_t handler_info;
32static void handler(
int signal, siginfo_t* info,
void* context) {
36 __atomic_store_n(&handled, 1, __ATOMIC_RELEASE);
39static int blocked_ignored_signals(
void) {
40 int failed = 0, masked = 0, installed = 0;
41 const int signals[] = {SIGCHLD, SIGUSR2};
42 sigset_t set, original, pending, one;
43 struct sigaction previous[2];
44 const struct timespec zero = {0};
46 CHECK(sigemptyset(&set) == 0 && sigaddset(&set, SIGCHLD) == 0 && sigaddset(&set, SIGUSR2) == 0);
47 CHECK(pthread_sigmask(SIG_BLOCK, &set, &original) == 0);
49 for (
int n = 0; n < 2; ++n) {
50 struct sigaction action = {.sa_handler = n ? SIG_IGN : SIG_DFL};
51 sigemptyset(&action.sa_mask);
52 CHECK(sigaction(signals[n], &action, &previous[n]) == 0);
55 for (
int n = 0; n < 2; ++n) {
56 CHECK(n ? sigqueue(getpid(), signals[n], (
union sigval){.sival_int = 77}) == 0
57 : kill(getpid(), signals[n]) == 0);
58 CHECK(sigpending(&pending) == 0 && sigismember(&pending, signals[n]) == 1);
59 CHECK(sigemptyset(&one) == 0 && sigaddset(&one, signals[n]) == 0);
60 CHECK(sigtimedwait(&one, &info, &zero) == signals[n] && info.si_signo == signals[n]);
61 CHECK(sigpending(&pending) == 0 && sigismember(&pending, signals[n]) == 0);
68 while (sigtimedwait(&set, &info, &zero) >= 0) {
70 for (
int n = 0; n < installed; ++n)
71 if (sigaction(signals[n], &previous[n], NULL))
73 if (pthread_sigmask(SIG_SETMASK, &original, NULL))
79int signal_timer_test_signals(
void) {
80 int failed = 0, masked = 0, worker_active = 0, handler_installed = 0;
81 sigset_t set, original, pending, one;
82 struct sigaction action = {.sa_sigaction = handler, .sa_flags = SA_SIGINFO}, old_action;
83 struct timespec zero = {0}, timeout = {0, 150000000};
87 void* bad = MAP_FAILED;
88 const int low = SIGRTMIN, high = SIGRTMAX;
89 const pid_t pid = getpid();
90 const uid_t uid = getuid();
92 CHECK(blocked_ignored_signals() == 0);
93 CHECK(high == 64 && low > 34);
94 CHECK(sigaddset(&set, SIGUSR1) == 0 && sigaddset(&set, low) == 0 &&
95 sigaddset(&set, low + 1) == 0 && sigaddset(&set, high) == 0);
96 CHECK(pthread_sigmask(SIG_BLOCK, &set, &original) == 0);
99 sigaddset(&one, SIGUSR1);
100 CHECK(sigqueue(pid, SIGUSR1, (
union sigval){.sival_int = 101}) == 0);
101 CHECK(sigqueue(pid, SIGUSR1, (
union sigval){.sival_int = 202}) == 0);
102 CHECK(sigpending(&pending) == 0 && sigismember(&pending, SIGUSR1) == 1);
103 CHECK(sigwaitinfo(&one, &info) == SIGUSR1 && info.si_code == SI_QUEUE && info.si_pid == pid &&
104 info.si_uid == uid && info.si_value.sival_int == 101);
105 CHECK(sigtimedwait(&one, &info, &zero) == -1 && errno == EAGAIN);
106 CHECK(sigpending(&pending) == 0 && sigismember(&pending, SIGUSR1) == 0);
108 CHECK(sigqueue(pid, high, (
union sigval){.sival_int = 640}) == 0);
109 CHECK(sigqueue(pid, low, (
union sigval){.sival_int = 350}) == 0);
110 CHECK(sigqueue(pid, low, (
union sigval){.sival_int = 351}) == 0);
111 CHECK(sigwaitinfo(&set, &info) == low && info.si_value.sival_int == 350);
112 CHECK(sigwaitinfo(&set, &info) == low && info.si_value.sival_int == 351);
113 CHECK(sigwaitinfo(&set, &info) == high && info.si_value.sival_int == 640);
115 sigaddset(&one, low);
116 for (
int n = 0; n < 16; ++n)
117 CHECK(sigqueue(pid, low, (
union sigval){.sival_int = n}) == 0);
118 CHECK(sigqueue(pid, low, (
union sigval){.sival_int = 16}) == -1 && errno == EAGAIN);
119 CHECK(kill(pid, low) == -1 && errno == EAGAIN);
120 CHECK(pthread_kill(pthread_self(), low) == EAGAIN);
121 CHECK(sigwaitinfo(&one, &info) == low && info.si_value.sival_int == 0);
122 CHECK(sigqueue(pid, low, (
union sigval){.sival_int = 16}) == 0);
123 for (
int n = 1; n <= 16; ++n)
124 CHECK(sigwaitinfo(&one, &info) == low && info.si_value.sival_int == n);
126 bad = mmap(NULL, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
127 CHECK(bad != MAP_FAILED);
128 CHECK(sigpending(bad) == -1 && errno == EFAULT);
129 CHECK(sigqueue(pid, low, (
union sigval){.sival_int = 999}) == 0);
130 CHECK(sigtimedwait(&one, bad, &zero) == -1 && errno == EFAULT);
131 CHECK(sigpending(&pending) == 0 && sigismember(&pending, low) == 1);
132 CHECK(sigwaitinfo(&one, &info) == low && info.si_value.sival_int == 999);
133 CHECK(syscall(SYS_rt_sigpending, &pending, 16) == -1 && errno == EINVAL);
134 struct timespec invalid = {0, 1000000000};
135 CHECK(sigtimedwait(&one, &info, &invalid) == -1 && errno == EINVAL);
136 int64_t started = st_now(CLOCK_MONOTONIC);
137 CHECK(sigtimedwait(&one, &info, &timeout) == -1 && errno == EAGAIN);
138 int64_t elapsed = st_now(CLOCK_MONOTONIC) - started;
139 CHECK(elapsed >= 100000000 && elapsed < 2000000000);
142 CHECK(pthread_create(&
worker, NULL, wait_for_signal, &
waiter) == 0);
144 CHECK(st_wait(&
waiter.entered, 1000) == 0);
146 CHECK(sigqueue(pid, low, (
union sigval){.sival_int = 501}) == 0);
147 CHECK(st_wait(&
waiter.done, 2000) == 0 && pthread_join(
worker, NULL) == 0);
149 CHECK(
waiter.result == low &&
waiter.info.si_value.sival_int == 501);
152 CHECK(pthread_create(&
worker, NULL, wait_for_signal, &
waiter) == 0);
154 CHECK(st_wait(&
waiter.entered, 1000) == 0);
156 CHECK(pthread_cancel(
worker) == 0 && st_wait(&
waiter.done, 2000) == 0);
158 CHECK(pthread_join(
worker, &result) == 0 && result == PTHREAD_CANCELED);
161 CHECK(sigaction(high, &action, &old_action) == 0);
162 handler_installed = 1;
164 sigaddset(&one, high);
165 CHECK(pthread_sigmask(SIG_UNBLOCK, &one, NULL) == 0);
166 CHECK(sigqueue(pid, high, (
union sigval){.sival_int = 7654}) == 0 &&
167 st_wait(&handled, 2000) == 0);
168 CHECK(handler_info.si_signo == high && handler_info.si_code == SI_QUEUE &&
169 handler_info.si_value.sival_int == 7654 && handler_info.si_pid == pid &&
170 handler_info.si_uid == uid);
175 if (st_wait(&
waiter.done, 1000) == 0)
176 pthread_join(
worker, NULL);
181 pthread_sigmask(SIG_BLOCK, &set, NULL);
182 while (sigtimedwait(&set, &info, &zero) >= 0) {
184 if (handler_installed)
185 sigaction(high, &old_action, NULL);
186 pthread_sigmask(SIG_SETMASK, &original, NULL);
188 if (bad != MAP_FAILED)