/* * Copyright (c) 2006 Daniel M. Eischen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id$ */ /* * gcc -Wall -D_POSIX_PTHREAD_SEMANTICS -o test_sigwaitone test_sigwaitone.c -lpthread */ #include #include #include #include #include #include #include static int sigcount = 0; static pthread_mutex_t waiter_mutex; static volatile int done = 0; static char *progname = NULL; static void usage(void) { fprintf(stderr, "Usage: %s sig [sig] ...\n", progname); exit (1); } static void * sigwaiter(void *arg) { int signo; sigset_t mask; sigset_t waitmask; /* Initially block everything. */ sigfillset(&mask); sigprocmask(SIG_SETMASK, &mask, NULL); /* Wait for any signal. */ sigemptyset(&waitmask); sigfillset(&waitmask); while (done == 0) { if (sigwait(&waitmask, &signo) != 0) { fprintf (stderr, "Unable to wait for signal, errno %d\n", errno); exit (1); } sigcount++; fprintf (stderr, "Sigwait caught signal %d\n", signo); /* * Allow the main thread to suspend the thread in * order to test pending signals. */ pthread_mutex_lock (&waiter_mutex); pthread_mutex_unlock (&waiter_mutex); } pthread_exit(arg); return (NULL); } static void send_process_signal (int signo) { if (kill(getpid (), signo) != 0) { fprintf (stderr, "Unable to send process signal, errno %d.\n", errno); exit (1); } } int main(int argc, char *argv[]) { pthread_mutexattr_t mattr; pthread_attr_t pattr; pthread_t tid; void * exit_status; sigset_t set; char junk; int signo; int i; progname = argv[0]; if (argc == 1) usage(); /* * Initialize the thread attribute. */ if ((pthread_attr_init(&pattr) != 0) || (pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE) != 0)) { fprintf(stderr, "Unable to initialize thread attributes.\n"); exit(1); } /* * Initialize and create a mutex. */ if ((pthread_mutexattr_init(&mattr) != 0) || (pthread_mutex_init(&waiter_mutex, &mattr) != 0)) { fprintf(stderr, "Unable to create waiter mutex.\n"); exit(1); } /* * Create the sigwaiter thread and allow it to start. */ if (pthread_create(&tid, &pattr, sigwaiter, NULL) != 0) { fprintf(stderr, "Unable to create thread.\n"); exit(1); } sleep(1); for (i = 1; i < argc; i++) { if (sscanf(argv[i], "%d%c", &signo, &junk) != 1) usage(); /* * Block the signal from the main (this) thread. */ sigemptyset(&set); sigaddset(&set, signo); sigprocmask(SIG_BLOCK, &set, NULL); /* Send the signal which should release the sigwait. */ sigcount = 0; send_process_signal(signo); sleep(1); if (sigcount != 1) fprintf(stderr, "FAIL: sigwait doesn't wake up for signal %d.\n", signo); } done = 1; pthread_kill(tid, SIGHUP); /* * Wait for the thread to finish. */ pthread_join(tid, &exit_status); return (0); }