NetBSD/regress/lib/libpthread/sigmask3/sigmask3.c
ad f87898b1c5 Signal masks are thread private, and there is no guarantee of the order in
which the two signal handlers in this test will execute, at least not beyond
SIGUSR1 being caught first, and SIGUSR2 being caught after that. One way
that it can fail erroneously is:

    2    kill(getpid(), SIGUSR1)
    2    Receive signal SIGUSR1
    2    kill(getpid(), SIGUSR2)
    1    Receive signal SIGUSR2
    1    Exit handler
    2    Exit handler

So if the handlers appear not to have run in sequence, at least verify
that they were run by different threads.
2006-12-26 20:29:03 +00:00

96 lines
1.8 KiB
C

#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
/* Test that signal masks are respected while threads are running. */
volatile sig_atomic_t flag;
volatile sig_atomic_t flag2;
volatile pthread_t thr_usr1;
volatile pthread_t thr_usr2;
void handler1(int, siginfo_t *, void *);
void handler2(int, siginfo_t *, void *);
void *threadroutine(void *);
void
handler1(int sig, siginfo_t *info, void *ctx)
{
kill(getpid(), SIGUSR2);
/*
* If the mask is properly set, SIGUSR2 will not be handled
* by the current thread until this handler returns.
*/
flag = 1;
thr_usr1 = pthread_self();
}
void
handler2(int sig, siginfo_t *info, void *ctx)
{
if (flag == 1)
flag = 2;
flag2 = 1;
thr_usr2 = pthread_self();
}
void *
threadroutine(void *arg)
{
kill(getpid(), SIGUSR1);
sleep(1);
if (flag == 2)
printf("Success: Both handlers ran in order\n");
else if (flag == 1 && flag2 == 1 && thr_usr1 != thr_usr2)
printf("Success: Handlers were invoked by different threads\n");
else {
printf("Failure: flag=%d, flag2=%d, thr1=%p, thr2=%p\n",
(int)flag, (int)flag2, (void *)thr_usr1, (void *)thr_usr2);
exit(1);
}
return NULL;
}
int
main(void)
{
struct sigaction act;
pthread_t thread;
int ret;
act.sa_sigaction = handler1;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGUSR2);
act.sa_flags = SA_SIGINFO;
ret = sigaction(SIGUSR1, &act, NULL);
if (ret) {
printf("sigaction: %d\n", ret);
exit(1);
}
act.sa_sigaction = handler2;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
ret = sigaction(SIGUSR2, &act, NULL);
ret = pthread_create(&thread, NULL, threadroutine, NULL);
if (ret) {
printf("pthread_create: %d\n", ret);
exit(1);
}
ret = pthread_join(thread, NULL);
if (ret) {
printf("pthread_join: %d\n", ret);
exit(1);
}
return 0;
}