]> mj.ucw.cz Git - libucw.git/blob - lib/sighandler.c
Merge with git+ssh://git.ucw.cz/projects/sherlock/GIT/sherlock.git
[libucw.git] / lib / sighandler.c
1 /*
2  *      UCW Library -- Catching of signals and calling callback functions
3  *
4  *      (c) 2004, Robert Spalek <robert@ucw.cz>
5  *      (c) 2006 Martin Mares <mj@ucw.cz>
6  */
7
8 #include "lib/lib.h"
9 #include "lib/threads.h"
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <signal.h>
14
15 static int sig_handler_nest[NSIG];
16 static struct sigaction sig_handler_old[NSIG];
17
18 static void
19 signal_handler_internal(int sig)
20 {
21   struct ucwlib_context *ctx = ucwlib_thread_context();
22   if (!ctx->signal_handlers || !ctx->signal_handlers[sig] || ctx->signal_handlers[sig](sig))
23     abort();
24 }
25
26 void
27 handle_signal(int signum)
28 {
29   ucwlib_lock();
30   if (!sig_handler_nest[signum]++)
31     {
32       struct sigaction act;
33       bzero(&act, sizeof(act));
34       act.sa_handler = signal_handler_internal;
35       act.sa_flags = SA_NODEFER;
36       if (sigaction(signum, &act, &sig_handler_old[signum]) < 0)
37         die("sigaction: %m");
38     }
39   ucwlib_unlock();
40 }
41
42 void
43 unhandle_signal(int signum)
44 {
45   ucwlib_lock();
46   ASSERT(sig_handler_nest[signum]);
47   if (!--sig_handler_nest[signum])
48     {
49       if (sigaction(signum, &sig_handler_old[signum], NULL) < 0)
50         die("sigaction: %m");
51     }
52   ucwlib_unlock();
53 }
54
55 sh_sighandler_t
56 set_signal_handler(int signum, sh_sighandler_t new)
57 {
58   struct ucwlib_context *ctx = ucwlib_thread_context();
59   if (!ctx->signal_handlers)
60     ctx->signal_handlers = xmalloc_zero(NSIG * sizeof(sh_sighandler_t));
61   sh_sighandler_t old = ctx->signal_handlers[signum];
62   ctx->signal_handlers[signum] = new;
63   return old;
64 }