159612Sjasone/* 259612Sjasone * Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com> 359612Sjasone * All rights reserved. 459612Sjasone * 559612Sjasone * Redistribution and use in source and binary forms, with or without 659612Sjasone * modification, are permitted provided that the following conditions 759612Sjasone * are met: 859612Sjasone * 1. Redistributions of source code must retain the above copyright 959612Sjasone * notice, this list of conditions and the following disclaimer. 1059612Sjasone * 2. Redistributions in binary form must reproduce the above copyright 1159612Sjasone * notice, this list of conditions and the following disclaimer in the 1259612Sjasone * documentation and/or other materials provided with the distribution. 1359612Sjasone * 3. All advertising materials mentioning features or use of this software 1459612Sjasone * must display the following acknowledgement: 1559612Sjasone * This product includes software developed by Daniel M. Eischen. 1659612Sjasone * 4. Neither the name of the author nor the names of any co-contributors 1759612Sjasone * may be used to endorse or promote products derived from this software 1859612Sjasone * without specific prior written permission. 1959612Sjasone * 2059612Sjasone * THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN AND CONTRIBUTORS ``AS IS'' 2159612Sjasone * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2259612Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2359612Sjasone * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2459612Sjasone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2559612Sjasone * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2659612Sjasone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2759612Sjasone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2859612Sjasone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2959612Sjasone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3059612Sjasone * SUCH DAMAGE. 3159612Sjasone * 3259612Sjasone * $FreeBSD: releng/10.3/lib/libkse/test/sigwait_d.c 76910 2001-05-20 23:10:30Z jasone $ 3359612Sjasone */ 3459612Sjasone#include <stdlib.h> 3559612Sjasone#include <unistd.h> 3659612Sjasone 3759612Sjasone#include <errno.h> 3859612Sjasone#include <pthread.h> 3959612Sjasone#include <signal.h> 4059612Sjasone#include <stdio.h> 4159612Sjasone#include <string.h> 4259612Sjasone 4359612Sjasone#if defined(_LIBC_R_) 4459612Sjasone#include <pthread_np.h> 4559612Sjasone#endif 4659612Sjasone 4759612Sjasonestatic int sigcounts[NSIG + 1]; 4859612Sjasonestatic sigset_t wait_mask; 4959612Sjasonestatic pthread_mutex_t waiter_mutex; 5059612Sjasone 5159612Sjasone 5259612Sjasonestatic void * 5359612Sjasonesigwaiter (void *arg) 5459612Sjasone{ 5559612Sjasone int signo; 5659612Sjasone sigset_t mask; 5759612Sjasone 5859612Sjasone /* Block SIGHUP */ 5959612Sjasone sigemptyset (&mask); 6059612Sjasone sigaddset (&mask, SIGHUP); 6159612Sjasone sigprocmask (SIG_BLOCK, &mask, NULL); 6259612Sjasone 6359612Sjasone while (sigcounts[SIGINT] == 0) { 6459612Sjasone if (sigwait (&wait_mask, &signo) != 0) { 6559612Sjasone fprintf (stderr, 6659612Sjasone "Unable to wait for signal, errno %d\n", 6759612Sjasone errno); 6859612Sjasone exit (1); 6959612Sjasone } 7059612Sjasone sigcounts[signo]++; 7159612Sjasone fprintf (stderr, "Sigwait caught signal %d\n", signo); 7259612Sjasone 7359612Sjasone /* Allow the main thread to prevent the sigwait. */ 7459612Sjasone pthread_mutex_lock (&waiter_mutex); 7559612Sjasone pthread_mutex_unlock (&waiter_mutex); 7659612Sjasone } 7759612Sjasone 7859612Sjasone pthread_exit (arg); 7959612Sjasone return (NULL); 8059612Sjasone} 8159612Sjasone 8259612Sjasone 8359612Sjasonestatic void 8459612Sjasonesighandler (int signo) 8559612Sjasone{ 8659612Sjasone fprintf (stderr, " -> Signal handler caught signal %d\n", signo); 8759612Sjasone 8859612Sjasone if ((signo >= 0) && (signo <= NSIG)) 8959612Sjasone sigcounts[signo]++; 9059612Sjasone} 9159612Sjasone 9259612Sjasonestatic void 9359612Sjasonesend_thread_signal (pthread_t tid, int signo) 9459612Sjasone{ 9559612Sjasone if (pthread_kill (tid, signo) != 0) { 9659612Sjasone fprintf (stderr, "Unable to send thread signal, errno %d.\n", 9759612Sjasone errno); 9859612Sjasone exit (1); 9959612Sjasone } 10059612Sjasone} 10159612Sjasone 10259612Sjasonestatic void 10359612Sjasonesend_process_signal (int signo) 10459612Sjasone{ 10559612Sjasone if (kill (getpid (), signo) != 0) { 10659612Sjasone fprintf (stderr, "Unable to send process signal, errno %d.\n", 10759612Sjasone errno); 10859612Sjasone exit (1); 10959612Sjasone } 11059612Sjasone} 11159612Sjasone 11259612Sjasone 11359612Sjasoneint main (int argc, char *argv[]) 11459612Sjasone{ 11559612Sjasone pthread_mutexattr_t mattr; 11659612Sjasone pthread_attr_t pattr; 11759612Sjasone pthread_t tid; 11859612Sjasone void * exit_status; 11959612Sjasone struct sigaction act; 12059612Sjasone 12159612Sjasone /* Initialize our signal counts. */ 12259612Sjasone memset ((void *) sigcounts, 0, NSIG * sizeof (int)); 12359612Sjasone 12459612Sjasone /* Setup our wait mask. */ 12559612Sjasone sigemptyset (&wait_mask); /* Default action */ 12659612Sjasone sigaddset (&wait_mask, SIGHUP); /* terminate */ 12759612Sjasone sigaddset (&wait_mask, SIGINT); /* terminate */ 12859612Sjasone sigaddset (&wait_mask, SIGQUIT); /* create core image */ 12959612Sjasone sigaddset (&wait_mask, SIGURG); /* ignore */ 13059612Sjasone sigaddset (&wait_mask, SIGIO); /* ignore */ 13159612Sjasone sigaddset (&wait_mask, SIGUSR1); /* terminate */ 13259612Sjasone 13359612Sjasone /* Ignore signals SIGHUP and SIGIO. */ 13459612Sjasone sigemptyset (&act.sa_mask); 13559612Sjasone sigaddset (&act.sa_mask, SIGHUP); 13659612Sjasone sigaddset (&act.sa_mask, SIGIO); 13759612Sjasone act.sa_handler = SIG_IGN; 13859612Sjasone act.sa_flags = 0; 13959612Sjasone sigaction (SIGHUP, &act, NULL); 14059612Sjasone sigaction (SIGIO, &act, NULL); 14159612Sjasone 14259612Sjasone /* Install a signal handler for SIGURG */ 14359612Sjasone sigemptyset (&act.sa_mask); 14459612Sjasone sigaddset (&act.sa_mask, SIGURG); 14559612Sjasone act.sa_handler = sighandler; 14659612Sjasone act.sa_flags = SA_RESTART; 14759612Sjasone sigaction (SIGURG, &act, NULL); 14859612Sjasone 14959612Sjasone /* Install a signal handler for SIGXCPU */ 15059612Sjasone sigemptyset (&act.sa_mask); 15159612Sjasone sigaddset (&act.sa_mask, SIGXCPU); 15259612Sjasone sigaction (SIGXCPU, &act, NULL); 15359612Sjasone 15459612Sjasone /* 15559612Sjasone * Initialize the thread attribute. 15659612Sjasone */ 15759612Sjasone if ((pthread_attr_init (&pattr) != 0) || 15859612Sjasone (pthread_attr_setdetachstate (&pattr, 15959612Sjasone PTHREAD_CREATE_JOINABLE) != 0)) { 16059612Sjasone fprintf (stderr, "Unable to initialize thread attributes.\n"); 16159612Sjasone exit (1); 16259612Sjasone } 16359612Sjasone 16459612Sjasone /* 16559612Sjasone * Initialize and create a mutex. 16659612Sjasone */ 16759612Sjasone if ((pthread_mutexattr_init (&mattr) != 0) || 16859612Sjasone (pthread_mutex_init (&waiter_mutex, &mattr) != 0)) { 16959612Sjasone fprintf (stderr, "Unable to create waiter mutex.\n"); 17059612Sjasone exit (1); 17159612Sjasone } 17259612Sjasone 17359612Sjasone /* 17459612Sjasone * Create the sigwaiter thread. 17559612Sjasone */ 17659612Sjasone if (pthread_create (&tid, &pattr, sigwaiter, NULL) != 0) { 17759612Sjasone fprintf (stderr, "Unable to create thread.\n"); 17859612Sjasone exit (1); 17959612Sjasone } 18059612Sjasone#if defined(_LIBC_R_) 18159612Sjasone pthread_set_name_np (tid, "sigwaiter"); 18259612Sjasone#endif 18359612Sjasone 18459612Sjasone /* 18559612Sjasone * Verify that an ignored signal doesn't cause a wakeup. 18659612Sjasone * We don't have a handler installed for SIGIO. 18759612Sjasone */ 18859612Sjasone send_thread_signal (tid, SIGIO); 18959612Sjasone sleep (1); 19059612Sjasone send_process_signal (SIGIO); 19159612Sjasone sleep (1); 19259612Sjasone if (sigcounts[SIGIO] != 0) 19359612Sjasone fprintf (stderr, 19459612Sjasone "FAIL: sigwait wakes up for ignored signal SIGIO.\n"); 19559612Sjasone 19659612Sjasone /* 19759612Sjasone * Verify that a signal with a default action of ignore, for 19859612Sjasone * which we have a signal handler installed, will release a sigwait. 19959612Sjasone */ 20059612Sjasone send_thread_signal (tid, SIGURG); 20159612Sjasone sleep (1); 20259612Sjasone send_process_signal (SIGURG); 20359612Sjasone sleep (1); 20459612Sjasone if (sigcounts[SIGURG] != 2) 20559612Sjasone fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGURG.\n"); 20659612Sjasone 20759612Sjasone /* 20859612Sjasone * Verify that a signal with a default action that terminates 20959612Sjasone * the process will release a sigwait. 21059612Sjasone */ 21159612Sjasone send_thread_signal (tid, SIGUSR1); 21259612Sjasone sleep (1); 21359612Sjasone send_process_signal (SIGUSR1); 21459612Sjasone sleep (1); 21559612Sjasone if (sigcounts[SIGUSR1] != 2) 21659612Sjasone fprintf (stderr, 21759612Sjasone "FAIL: sigwait doesn't wake up for SIGUSR1.\n"); 21859612Sjasone 21959612Sjasone /* 22059612Sjasone * Verify that if we install a signal handler for a previously 22159612Sjasone * ignored signal, an occurrence of this signal will release 22259612Sjasone * the (already waiting) sigwait. 22359612Sjasone */ 22459612Sjasone 22559612Sjasone /* Install a signal handler for SIGHUP. */ 22659612Sjasone sigemptyset (&act.sa_mask); 22759612Sjasone sigaddset (&act.sa_mask, SIGHUP); 22859612Sjasone act.sa_handler = sighandler; 22959612Sjasone act.sa_flags = SA_RESTART; 23059612Sjasone sigaction (SIGHUP, &act, NULL); 23159612Sjasone 23259612Sjasone /* Sending SIGHUP should release the sigwait. */ 23359612Sjasone send_process_signal (SIGHUP); 23459612Sjasone sleep (1); 23559612Sjasone send_thread_signal (tid, SIGHUP); 23659612Sjasone sleep (1); 23759612Sjasone if (sigcounts[SIGHUP] != 2) 23859612Sjasone fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n"); 23959612Sjasone 24059612Sjasone /* 24159612Sjasone * Verify that a pending signal in the waiters mask will 24259612Sjasone * cause sigwait to return the pending signal. We do this 24359612Sjasone * by taking the waiters mutex and signaling the waiter to 24459612Sjasone * release him from the sigwait. The waiter will block 24559612Sjasone * on taking the mutex, and we can then send the waiter a 24659612Sjasone * signal which should be added to his pending signals. 24759612Sjasone * The next time the waiter does a sigwait, he should 24859612Sjasone * return with the pending signal. 24959612Sjasone */ 25059612Sjasone sigcounts[SIGHUP] = 0; 25159612Sjasone pthread_mutex_lock (&waiter_mutex); 25259612Sjasone /* Release the waiter from sigwait. */ 25359612Sjasone send_process_signal (SIGHUP); 25459612Sjasone sleep (1); 25559612Sjasone if (sigcounts[SIGHUP] != 1) 25659612Sjasone fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n"); 25759612Sjasone /* 25859612Sjasone * Add SIGHUP to the process pending signals. Since there is 25959612Sjasone * a signal handler installed for SIGHUP and this signal is 26059612Sjasone * blocked from the waiter thread and unblocked in the main 26159612Sjasone * thread, the signal handler should be called once for SIGHUP. 26259612Sjasone */ 26359612Sjasone send_process_signal (SIGHUP); 26459612Sjasone /* Release the waiter thread and allow him to run. */ 26559612Sjasone pthread_mutex_unlock (&waiter_mutex); 26659612Sjasone sleep (1); 26759612Sjasone if (sigcounts[SIGHUP] != 2) 26859612Sjasone fprintf (stderr, 26959612Sjasone "FAIL: sigwait doesn't return for pending SIGHUP.\n"); 27059612Sjasone 27159612Sjasone /* 27259612Sjasone * Repeat the above test using pthread_kill and SIGUSR1. 27359612Sjasone */ 27459612Sjasone sigcounts[SIGUSR1] = 0; 27559612Sjasone pthread_mutex_lock (&waiter_mutex); 27659612Sjasone /* Release the waiter from sigwait. */ 27759612Sjasone send_thread_signal (tid, SIGUSR1); 27859612Sjasone sleep (1); 27959612Sjasone if (sigcounts[SIGUSR1] != 1) 28059612Sjasone fprintf (stderr, 28159612Sjasone "FAIL: sigwait doesn't wake up for SIGUSR1.\n"); 28276910Sjasone /* Add SIGUSR1 to the waiters pending signals. */ 28359612Sjasone send_thread_signal (tid, SIGUSR1); 28459612Sjasone /* Release the waiter thread and allow him to run. */ 28559612Sjasone pthread_mutex_unlock (&waiter_mutex); 28659612Sjasone sleep (1); 28759612Sjasone if (sigcounts[SIGUSR1] != 2) 28859612Sjasone fprintf (stderr, 28959612Sjasone "FAIL: sigwait doesn't return for pending SIGUSR1.\n"); 29059612Sjasone 29159612Sjasone /* 29259612Sjasone * Verify that we can still kill the process for a signal 29359612Sjasone * not being waited on by sigwait. 29459612Sjasone */ 29559612Sjasone send_process_signal (SIGPIPE); 29659612Sjasone fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n"); 29759612Sjasone 29859612Sjasone /* 29959612Sjasone * Wait for the thread to finish. 30059612Sjasone */ 30159612Sjasone pthread_join (tid, &exit_status); 30259612Sjasone 30359612Sjasone return (0); 30459612Sjasone} 305