X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fsighandler.c;h=2739ba10304023114abe01dcfa8226b2a67b7e35;hb=6a0d147c9fcec363172649425f76a71b5af8ffab;hp=ca8269083afc44ebc7836ebc0c6f41e9acecaedc;hpb=638afb438a73eee8efa9dc6179c3cd39572847cf;p=libucw.git diff --git a/lib/sighandler.c b/lib/sighandler.c index ca826908..2739ba10 100644 --- a/lib/sighandler.c +++ b/lib/sighandler.c @@ -2,41 +2,63 @@ * UCW Library -- Catching of signals and calling callback functions * * (c) 2004, Robert Spalek + * (c) 2006 Martin Mares */ #include "lib/lib.h" +#include "lib/threads.h" #include #include #include -sh_sighandler_t signal_handler[_NSIG]; +static int sig_handler_nest[NSIG]; +static struct sigaction sig_handler_old[NSIG]; static void signal_handler_internal(int sig) { - if (signal_handler[sig]) - { - if (!signal_handler[sig](sig)) - return; - } - abort(); + struct ucwlib_context *ctx = ucwlib_thread_context(); + if (!ctx->signal_handlers || !ctx->signal_handlers[sig] || ctx->signal_handlers[sig](sig)) + abort(); } void -handle_signal(int signum, struct sigaction *oldact) +handle_signal(int signum) { - struct sigaction act; - bzero(&act, sizeof(act)); - act.sa_handler = signal_handler_internal; - act.sa_flags = SA_NOMASK; - if (sigaction(signum, &act, oldact) < 0) - die("sigaction: %m"); + ucwlib_lock(); + if (!sig_handler_nest[signum]++) + { + struct sigaction act; + bzero(&act, sizeof(act)); + act.sa_handler = signal_handler_internal; + act.sa_flags = SA_NODEFER; + if (sigaction(signum, &act, &sig_handler_old[signum]) < 0) + die("sigaction: %m"); + } + ucwlib_unlock(); } void -unhandle_signal(int signum, struct sigaction *oldact) +unhandle_signal(int signum) { - if (sigaction(signum, oldact, NULL) < 0) - die("sigaction: %m"); + ucwlib_lock(); + ASSERT(sig_handler_nest[signum]); + if (!--sig_handler_nest[signum]) + { + if (sigaction(signum, &sig_handler_old[signum], NULL) < 0) + die("sigaction: %m"); + } + ucwlib_unlock(); +} + +sh_sighandler_t +set_signal_handler(int signum, sh_sighandler_t new) +{ + struct ucwlib_context *ctx = ucwlib_thread_context(); + if (!ctx->signal_handlers) + ctx->signal_handlers = xmalloc_zero(NSIG * sizeof(sh_sighandler_t)); + sh_sighandler_t old = ctx->signal_handlers[signum]; + ctx->signal_handlers[signum] = new; + return old; }