#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <pthread_np.h>
#include "test.h"
static int sigcounts[NSIG + 1];
static int sigfifo[NSIG + 1];
static int fifo_depth = 0;
static sigset_t suspender_mask;
static pthread_t suspender_tid;
static void *
sigsuspender (void *arg)
{
int save_count, status, i;
sigset_t run_mask;
SET_NAME("sigsuspender");
sigfillset (&run_mask);
CHECKe(sigprocmask (SIG_SETMASK, &run_mask, NULL));
sigfillset (&suspender_mask);
sigdelset (&suspender_mask, SIGINT);
sigdelset (&suspender_mask, SIGHUP);
sigdelset (&suspender_mask, SIGQUIT);
sigdelset (&suspender_mask, SIGURG);
sigdelset (&suspender_mask, SIGIO);
sigdelset (&suspender_mask, SIGUSR2);
sigdelset (&suspender_mask, SIGSTOP);
sigdelset (&suspender_mask, SIGKILL);
while (sigcounts[SIGINT] == 0) {
save_count = sigcounts[SIGUSR2];
status = sigsuspend (&suspender_mask);
if ((status == 0) || (errno != EINTR)) {
DIE(errno, "Unable to suspend for signals, "
"return value %d\n",
status);
}
for (i = 0; i < fifo_depth; i++)
printf ("Sigsuspend woke up by signal %d (%s)\n",
sigfifo[i], strsignal(sigfifo[i]));
fifo_depth = 0;
}
return (arg);
}
static void
sighandler (int signo)
{
int save_errno = errno;
char buf[8192];
sigset_t set;
sigset_t tmp;
pthread_t self;
if ((signo >= 0) && (signo <= NSIG))
sigcounts[signo]++;
self = pthread_self ();
if (self == suspender_tid) {
sigfifo[fifo_depth] = signo;
fifo_depth++;
snprintf(buf, sizeof buf,
" -> Suspender thread signal handler caught "
"signal %d (%s)\n", signo, strsignal(signo));
write(STDOUT_FILENO, buf, strlen(buf));
sigprocmask (SIG_SETMASK, NULL, &set);
tmp = suspender_mask;
sigaddset(&tmp, signo);
sigdelset(&tmp, SIGTHR);
sigdelset(&set, SIGTHR);
ASSERT(set == tmp);
} else {
snprintf(buf, sizeof buf,
" -> Main thread signal handler caught "
"signal %d (%s)\n", signo, strsignal(signo));
write(STDOUT_FILENO, buf, strlen(buf));
}
errno = save_errno;
}
int main (int argc, char *argv[])
{
pthread_attr_t pattr;
struct sigaction act;
sigset_t oldset;
sigset_t newset;
memset ((void *) sigcounts, 0, NSIG * sizeof (int));
sigemptyset (&act.sa_mask);
sigaddset (&act.sa_mask, SIGIO);
act.sa_handler = SIG_IGN;
act.sa_flags = 0;
CHECKe(sigaction (SIGIO, &act, NULL));
sigemptyset (&act.sa_mask);
sigaddset (&act.sa_mask, SIGURG);
act.sa_handler = sighandler;
act.sa_flags = SA_RESTART;
CHECKe(sigaction (SIGURG, &act, NULL));
sigemptyset (&act.sa_mask);
sigaddset (&act.sa_mask, SIGXCPU);
CHECKe(sigaction (SIGXCPU, &act, NULL));
CHECKe(sigprocmask (SIG_SETMASK, NULL, &oldset));
newset = oldset;
sigaddset (&newset, SIGUSR1);
sigaddset (&newset, SIGUSR2);
CHECKe(sigprocmask (SIG_SETMASK, &newset, NULL));
sigemptyset (&act.sa_mask);
sigaddset (&act.sa_mask, SIGUSR1);
sigaddset (&act.sa_mask, SIGUSR2);
act.sa_handler = sighandler;
act.sa_flags = SA_RESTART;
CHECKe(sigaction (SIGUSR1, &act, NULL));
CHECKe(sigaction (SIGUSR2, &act, NULL));
CHECKr(pthread_attr_init (&pattr));
CHECKr(pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE));
CHECKr(pthread_create (&suspender_tid, &pattr, sigsuspender, NULL));
CHECKr(pthread_kill (suspender_tid, SIGIO));
sleep (1);
CHECKe(kill (getpid (), SIGIO));
sleep (1);
ASSERT(sigcounts[SIGIO] == 0);
CHECKr(pthread_kill (suspender_tid, SIGURG));
sleep (1);
CHECKe(kill (getpid (), SIGURG));
sleep (1);
ASSERT(sigcounts[SIGURG] == 2);
CHECKr(pthread_kill (suspender_tid, SIGUSR2));
sleep (1);
CHECKe(kill (getpid (), SIGUSR2));
sleep (1);
ASSERT(sigcounts[SIGUSR2] == 2);
CHECKr(pthread_kill (suspender_tid, SIGUSR1));
sleep (1);
CHECKe(kill (getpid (), SIGUSR1));
sleep (1);
ASSERT(sigcounts[SIGUSR1] == 0);
#if 0
CHECKe(kill (getpid (), SIGPIPE));
PANIC("SIGPIPE did not terminate process");
CHECKr(pthread_join (suspender_tid, NULL));
#endif
SUCCEED;
}