2
* Asynchronous signal delivery functions.
4
* Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
14
#include <proto/signal.h>
15
#include <proto/log.h>
17
/* Principle : we keep an in-order list of the first occurrence of all received
18
* signals. All occurrences of a same signal are grouped though. The signal
19
* queue does not need to be deeper than the number of signals we can handle.
20
* The handlers will be called asynchronously with the signal number. They can
21
* check themselves the number of calls by checking the descriptor this signal.
24
int signal_queue_len; /* length of signal queue, <= MAX_SIGNAL (1 entry per signal max) */
25
int signal_queue[MAX_SIGNAL]; /* in-order queue of received signals */
26
struct signal_descriptor signal_state[MAX_SIGNAL];
32
memset(signal_queue, 0, sizeof(signal_queue));
33
memset(signal_state, 0, sizeof(signal_state));
34
sigfillset(&blocked_sig);
37
void signal_handler(int sig)
39
if (sig < 0 || sig > MAX_SIGNAL || !signal_state[sig].handler) {
40
/* unhandled signal */
41
qfprintf(stderr, "Received unhandled signal %d. Signal has been disabled.\n", sig);
46
if (!signal_state[sig].count) {
47
/* signal was not queued yet */
48
if (signal_queue_len < MAX_SIGNAL)
49
signal_queue[signal_queue_len++] = sig;
51
qfprintf(stderr, "Signal %d : signal queue is unexpectedly full.\n", sig);
53
signal_state[sig].count++;
54
signal(sig, signal_handler); /* re-arm signal */
57
/* Register a handler for signal <sig>. Set it to NULL, SIG_DFL or SIG_IGN to
58
* remove the handler. The signal's queue is flushed and the signal is really
59
* registered (or unregistered) for the process. The interface is the same as
60
* for standard signal delivery, except that the handler does not need to rearm
61
* the signal itself (it can disable it however).
63
void signal_register(int sig, void (*handler)(int))
65
if (sig < 0 || sig > MAX_SIGNAL) {
66
qfprintf(stderr, "Failed to register signal %d : out of range [0..%d].\n", sig, MAX_SIGNAL);
70
signal_state[sig].count = 0;
74
if (handler != SIG_IGN && handler != SIG_DFL) {
75
signal_state[sig].handler = handler;
76
signal(sig, signal_handler);
79
signal_state[sig].handler = NULL;
84
/* Call handlers of all pending signals and clear counts and queue length. The
85
* handlers may unregister themselves by calling signal_register() while they
86
* are called, just like it is done with normal signal handlers.
87
* Note that it is more efficient to call the inline version which checks the
88
* queue length before getting here.
90
void __signal_process_queue()
93
struct signal_descriptor *desc;
96
/* block signal delivery during processing */
97
sigprocmask(SIG_SETMASK, &blocked_sig, &old_sig);
99
for (cur_pos = 0; cur_pos < signal_queue_len; cur_pos++) {
100
sig = signal_queue[cur_pos];
101
desc = &signal_state[sig];
108
signal_queue_len = 0;
110
/* restore signal delivery */
111
sigprocmask(SIG_SETMASK, &old_sig, NULL);