signal.c

Go to the documentation of this file.
00001 /*      $Id: signal.nc 22 2007-03-24 21:16:33Z mark $   */
00002 
00003 /*
00004  * Copyright (c) 2004, 2005, 2006, 2007 Mark Heily <devel@heily.com>
00005  *
00006  * Permission to use, copy, modify, and distribute this software for any
00007  * purpose with or without fee is hereby granted, provided that the above
00008  * copyright notice and this permission notice appear in all copies.
00009  *
00010  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00011  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00012  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00013  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00014  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00015  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00016  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00017  */
00018 
00025 #include "config.h"
00026 
00027 #include <assert.h>
00028 #include <err.h>
00029 #include <signal.h>
00030 #include <stdlib.h>
00031 #include <sys/signal.h>
00032 #include <sys/types.h>
00033 #include <sys/wait.h>
00034 
00035 #include "pnotify-internal.h"
00036 #include "pnotify.h"
00037 
00039 static struct pnotify_ctx *SIGNAL_CTX[NSIG + 1];
00040 static pthread_mutex_t SIGNAL_CTX_MUTEX = PTHREAD_MUTEX_INITIALIZER;
00041 
00042 
00049 int
00050 pn_trap_signal(struct pnotify_ctx *ctx, int signum)
00051 {
00052         int retval = 0;
00053 
00054         assert(ctx && signum);
00055 
00056         mutex_lock(ctx);
00057         pthread_mutex_lock(&SIGNAL_CTX_MUTEX);
00058 
00059         /* Update the SIGNAL structure */
00060         SIGNAL_CTX[signum] = ctx;
00061 
00062         pthread_mutex_unlock(&SIGNAL_CTX_MUTEX);
00063         mutex_unlock(ctx);
00064 
00065         return retval;
00066 }
00067 
00068 
00069 static void
00070 default_signal_handler(int signum)
00071 {
00072         switch (signum) {
00073 
00074                 case SIGCHLD:
00075                         /* Ignored */
00076                         break;
00077 
00078                 case SIGINT:
00079                         fprintf(stderr, "Caught SIGINT, exiting..\n");
00080                         exit(1);
00081                         break;
00082 
00083                 case SIGTERM:
00084                         fprintf(stderr, "Caught SIGTERM, exiting..\n");
00085                         exit(1);
00086                         break;
00087                 default:
00088                         fprintf(stderr, "Caught signal %d but no handler..\n", signum);
00089         }
00090 }
00091 
00092 void *
00093 pn_signal_loop(void * unused)
00094 {
00095         sigset_t signal_set;
00096         struct pnotify_event *evt;
00097         struct pnotify_ctx *ctx;
00098         int signum;
00099 
00100         /* Avoid a compiler warning */
00101         ctx = unused;
00102 
00103         /* Loop forever waiting for signals */
00104         for (;;) {
00105 
00106                 /* Wait for a signal */
00107                 sigfillset(&signal_set);
00108                 sigdelset(&signal_set, SIGALRM);
00109                 sigwait(&signal_set, &signum);
00110 
00111                 /* Get the delivery context, or ignore the signal */
00112                 pthread_mutex_lock(&SIGNAL_CTX_MUTEX);
00113                 ctx = SIGNAL_CTX[signum];
00114                 pthread_mutex_unlock(&SIGNAL_CTX_MUTEX);
00115                 if (!ctx) {
00116                         default_signal_handler(signum);
00117                         continue;
00118                 }
00119 
00120                 /* Create a new event structure */
00121                 if ((evt = calloc(1, sizeof(*evt))) == NULL)
00122                         err(1, "calloc(3)");
00123                 evt->watch = pn_get_watch_by_id(signum);
00124                 evt->mask = PN_SIGNAL;
00125 
00126                 /* Add the event to an event queue */
00127                 pn_event_add(ctx, evt);
00128         }
00129 
00130         return NULL;
00131 }
00132 
00133 void
00134 pn_mask_signals()
00135 {
00136         sigset_t signal_set;
00137 
00138         /* Block all signals */
00139         sigfillset(&signal_set);
00140         if (pthread_sigmask(SIG_BLOCK, &signal_set, NULL) != 0)
00141                 err(1, "pthread_sigmask(3)");
00142 }

Generated on Wed Aug 22 23:15:42 2007 for pnotify by  doxygen 1.5.1