X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fsignals.c;h=06c2e75dfdf6958d1b674d028b9a7fdcb9da9464;hb=2c57a420432de88b8a6f9ee54642c3841577ad7b;hp=eabbcc382c03c28a1dbc78a1e8cb0180955e3a24;hpb=a4af00400a835eb87569ba40e21874c05e872c0f;p=sliver-openvswitch.git diff --git a/lib/signals.c b/lib/signals.c index eabbcc382..06c2e75df 100644 --- a/lib/signals.c +++ b/lib/signals.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009 Nicira Networks. + * Copyright (c) 2008, 2009, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,18 @@ #include #include "signals.h" -#include #include #include #include +#include #include #include "poll-loop.h" #include "socket-util.h" +#include "type-props.h" #include "util.h" +#include "vlog.h" + +VLOG_DEFINE_THIS_MODULE(signals); #if defined(_NSIG) #define N_SIGNALS _NSIG @@ -36,6 +40,7 @@ #endif struct signal { + struct sigaction saved_sa; int signr; }; @@ -57,11 +62,7 @@ signal_init(void) static bool inited; if (!inited) { inited = true; - if (pipe(fds)) { - ovs_fatal(errno, "could not create pipe"); - } - set_nonblocking(fds[0]); - set_nonblocking(fds[1]); + xpipe_nonblocking(fds); } } @@ -76,22 +77,31 @@ signal_register(int signr) signal_init(); + s = xmalloc(sizeof *s); + s->signr = signr; + /* Set up signal handler. */ - assert(signr >= 1 && signr < N_SIGNALS); + ovs_assert(signr >= 1 && signr < N_SIGNALS); memset(&sa, 0, sizeof sa); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - if (sigaction(signr, &sa, NULL)) { - ovs_fatal(errno, "sigaction(%d) failed", signr); - } + xsigaction(signr, &sa, &s->saved_sa); - /* Return structure. */ - s = xmalloc(sizeof *s); - s->signr = signr; return s; } +/* Unregisters the handler for 's', restores the signal handler that was in + * effect before signal_register() was called, and frees 's'. */ +void +signal_unregister(struct signal *s) +{ + if (s) { + xsigaction(s->signr, &s->saved_sa, NULL); + free(s); + } +} + /* Returns true if signal 's' has been received since the last call to this * function with argument 's'. */ bool @@ -126,3 +136,41 @@ signal_handler(int signr) signaled[signr] = true; } } + +/* Returns the name of signal 'signum' as a string. The string may be in a + * static buffer that is reused from one call to the next. + * + * The string is probably a (possibly multi-word) description of the signal + * (e.g. "Hangup") instead of just the stringified version of the macro + * (e.g. "SIGHUP"). */ +const char * +signal_name(int signum) +{ + const char *name = NULL; +#ifdef HAVE_STRSIGNAL + name = strsignal(signum); +#endif + if (!name) { + static char buffer[7 + INT_STRLEN(int) + 1]; + sprintf(buffer, "signal %d", signum); + name = buffer; + } + return name; +} + +void +xsigaction(int signum, const struct sigaction *new, struct sigaction *old) +{ + if (sigaction(signum, new, old)) { + VLOG_FATAL("sigaction(%s) failed (%s)", + signal_name(signum), strerror(errno)); + } +} + +void +xsigprocmask(int how, const sigset_t *new, sigset_t *old) +{ + if (sigprocmask(how, new, old)) { + VLOG_FATAL("sigprocmask failed (%s)", strerror(errno)); + } +}