X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fsighandler.c;h=2739ba10304023114abe01dcfa8226b2a67b7e35;hb=39d5e9acc6d93c07cbb408fe27144c8a485499ac;hp=00bd81ff7fc11125101aaae74202d38cda4cbdd5;hpb=f5cb619eb24ba3501a1b1a1c3edd93689714b1f6;p=libucw.git diff --git a/lib/sighandler.c b/lib/sighandler.c index 00bd81ff..2739ba10 100644 --- a/lib/sighandler.c +++ b/lib/sighandler.c @@ -1,27 +1,64 @@ /* - * Catching of signals and calling callback functions + * 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 -my_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) { - signal(sig, signal_handler_internal); - if (signal_handler[sig]) - signal_handler[sig](); - abort(); + struct ucwlib_context *ctx = ucwlib_thread_context(); + if (!ctx->signal_handlers || !ctx->signal_handlers[sig] || ctx->signal_handlers[sig](sig)) + abort(); } -void * +void handle_signal(int signum) { - return signal(signum, signal_handler_internal); + 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) +{ + 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; }