1 /*
2 * Asynchronous signal delivery functions.
3 *
4 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
5 *
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.
10 *
11 */
12
13 #include <signal.h>
14 #include <string.h>
15
16 #include <haproxy/errors.h>
17 #include <haproxy/signal.h>
18 #include <haproxy/task.h>
19
20 /* Principle : we keep an in-order list of the first occurrence of all received
21 * signals. All occurrences of a same signal are grouped though. The signal
22 * queue does not need to be deeper than the number of signals we can handle.
23 * The handlers will be called asynchronously with the signal number. They can
24 * check themselves the number of calls by checking the descriptor this signal.
25 */
26
27 int signal_queue_len; /* length of signal queue, <= MAX_SIGNAL (1 entry per signal max) */
28 int signal_queue[MAX_SIGNAL]; /* in-order queue of received signals */
29 struct signal_descriptor signal_state[MAX_SIGNAL];
30 sigset_t blocked_sig;
31 int signal_pending = 0; /* non-zero if t least one signal remains unprocessed */
32
33 DECLARE_STATIC_POOL(pool_head_sig_handlers, "sig_handlers", sizeof(struct sig_handler));
34
35 /* Common signal handler, used by all signals. Received signals are queued.
36 * Signal number zero has a specific status, as it cannot be delivered by the
37 * system, any function may call it to perform asynchronous signal delivery.
38 */
signal_handler(int sig)39 void signal_handler(int sig)
40 {
41 if (sig < 0 || sig >= MAX_SIGNAL) {
42 /* unhandled signal */
43 signal(sig, SIG_IGN);
44 qfprintf(stderr, "Received unhandled signal %d. Signal has been disabled.\n", sig);
45 return;
46 }
47
48 if (!signal_state[sig].count) {
49 /* signal was not queued yet */
50 if (signal_queue_len < MAX_SIGNAL)
51 signal_queue[signal_queue_len++] = sig;
52 else
53 qfprintf(stderr, "Signal %d : signal queue is unexpectedly full.\n", sig);
54 }
55
56 signal_state[sig].count++;
57 if (sig)
58 signal(sig, signal_handler); /* re-arm signal */
59 }
60
61 /* Call handlers of all pending signals and clear counts and queue length. The
62 * handlers may unregister themselves by calling signal_register() while they
63 * are called, just like it is done with normal signal handlers.
64 * Note that it is more efficient to call the inline version which checks the
65 * queue length before getting here.
66 */
__signal_process_queue()67 void __signal_process_queue()
68 {
69 int sig, cur_pos = 0;
70 struct signal_descriptor *desc;
71 sigset_t old_sig;
72
73 /* block signal delivery during processing */
74 ha_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
75
76 /* It is important that we scan the queue forwards so that we can
77 * catch any signal that would have been queued by another signal
78 * handler. That allows real signal handlers to redistribute signals
79 * to tasks subscribed to signal zero.
80 */
81 for (cur_pos = 0; cur_pos < signal_queue_len; cur_pos++) {
82 sig = signal_queue[cur_pos];
83 desc = &signal_state[sig];
84 if (desc->count) {
85 struct sig_handler *sh, *shb;
86 list_for_each_entry_safe(sh, shb, &desc->handlers, list) {
87 if ((sh->flags & SIG_F_TYPE_FCT) && sh->handler)
88 ((void (*)(struct sig_handler *))sh->handler)(sh);
89 else if ((sh->flags & SIG_F_TYPE_TASK) && sh->handler)
90 task_wakeup(sh->handler, TASK_WOKEN_SIGNAL);
91 }
92 desc->count = 0;
93 }
94 }
95 signal_queue_len = 0;
96
97 /* restore signal delivery */
98 ha_sigmask(SIG_SETMASK, &old_sig, NULL);
99 }
100
101 /* perform minimal intializations */
signal_init()102 static void signal_init()
103 {
104 int sig;
105
106 signal_queue_len = 0;
107 memset(signal_queue, 0, sizeof(signal_queue));
108 memset(signal_state, 0, sizeof(signal_state));
109
110 sigfillset(&blocked_sig);
111 sigdelset(&blocked_sig, SIGPROF);
112 /* man sigprocmask: If SIGBUS, SIGFPE, SIGILL, or SIGSEGV are
113 generated while they are blocked, the result is undefined, unless
114 the signal was generated by kill(2),
115 sigqueue(3), or raise(3).
116 Do not ignore WDTSIG or DEBUGSIG either, or it may deadlock the
117 watchdog */
118 sigdelset(&blocked_sig, SIGBUS);
119 sigdelset(&blocked_sig, SIGFPE);
120 sigdelset(&blocked_sig, SIGILL);
121 sigdelset(&blocked_sig, SIGSEGV);
122 #ifdef DEBUGSIG
123 sigdelset(&blocked_sig, DEBUGSIG);
124 #endif
125 #ifdef WDTSIG
126 sigdelset(&blocked_sig, WDTSIG);
127 #endif
128 for (sig = 0; sig < MAX_SIGNAL; sig++)
129 LIST_INIT(&signal_state[sig].handlers);
130 }
131
132 /*
133 * This function should be called to unblock all signals
134 */
haproxy_unblock_signals()135 void haproxy_unblock_signals()
136 {
137 sigset_t set;
138
139 /* Ensure signals are not blocked. Some shells or service managers may
140 * accidentally block all of our signals unfortunately, causing lots of
141 * zombie processes to remain in the background during reloads.
142 */
143 sigemptyset(&set);
144 ha_sigmask(SIG_SETMASK, &set, NULL);
145 }
146
147 /* releases all registered signal handlers */
deinit_signals()148 void deinit_signals()
149 {
150 int sig;
151 struct sig_handler *sh, *shb;
152
153 for (sig = 0; sig < MAX_SIGNAL; sig++) {
154 if (sig != SIGPROF)
155 signal(sig, SIG_DFL);
156 list_for_each_entry_safe(sh, shb, &signal_state[sig].handlers, list) {
157 LIST_DELETE(&sh->list);
158 pool_free(pool_head_sig_handlers, sh);
159 }
160 }
161 }
162
163 /* Register a function and an integer argument on a signal. A pointer to the
164 * newly allocated sig_handler is returned, or NULL in case of any error. The
165 * caller is responsible for unregistering the function when not used anymore.
166 * Note that passing a NULL as the function pointer enables interception of the
167 * signal without processing, which is identical to SIG_IGN. If the signal is
168 * zero (which the system cannot deliver), only internal functions will be able
169 * to notify the registered functions.
170 */
signal_register_fct(int sig,void (* fct)(struct sig_handler *),int arg)171 struct sig_handler *signal_register_fct(int sig, void (*fct)(struct sig_handler *), int arg)
172 {
173 struct sig_handler *sh;
174
175 if (sig < 0 || sig >= MAX_SIGNAL)
176 return NULL;
177
178 if (sig)
179 signal(sig, fct ? signal_handler : SIG_IGN);
180
181 if (!fct)
182 return NULL;
183
184 sh = pool_alloc(pool_head_sig_handlers);
185 if (!sh)
186 return NULL;
187
188 sh->handler = fct;
189 sh->arg = arg;
190 sh->flags = SIG_F_TYPE_FCT;
191 LIST_APPEND(&signal_state[sig].handlers, &sh->list);
192 return sh;
193 }
194
195 /* Register a task and a wake-up reason on a signal. A pointer to the newly
196 * allocated sig_handler is returned, or NULL in case of any error. The caller
197 * is responsible for unregistering the task when not used anymore. Note that
198 * passing a NULL as the task pointer enables interception of the signal
199 * without processing, which is identical to SIG_IGN. If the signal is zero
200 * (which the system cannot deliver), only internal functions will be able to
201 * notify the registered functions.
202 */
signal_register_task(int sig,struct task * task,int reason)203 struct sig_handler *signal_register_task(int sig, struct task *task, int reason)
204 {
205 struct sig_handler *sh;
206
207 if (sig < 0 || sig >= MAX_SIGNAL)
208 return NULL;
209
210 if (sig)
211 signal(sig, signal_handler);
212
213 if (!task)
214 return NULL;
215
216 sh = pool_alloc(pool_head_sig_handlers);
217 if (!sh)
218 return NULL;
219
220 sh->handler = task;
221 sh->arg = reason & ~TASK_WOKEN_ANY;
222 sh->flags = SIG_F_TYPE_TASK;
223 LIST_APPEND(&signal_state[sig].handlers, &sh->list);
224 return sh;
225 }
226
227 /* Immediately unregister a handler so that no further signals may be delivered
228 * to it. The struct is released so the caller may not reference it anymore.
229 */
signal_unregister_handler(struct sig_handler * handler)230 void signal_unregister_handler(struct sig_handler *handler)
231 {
232 LIST_DELETE(&handler->list);
233 pool_free(pool_head_sig_handlers, handler);
234 }
235
236 /* Immediately unregister a handler so that no further signals may be delivered
237 * to it. The handler struct does not need to be known, only the function or
238 * task pointer. This method is expensive because it scans all the list, so it
239 * should only be used for rare cases (eg: exit). The struct is released so the
240 * caller may not reference it anymore.
241 */
signal_unregister_target(int sig,void * target)242 void signal_unregister_target(int sig, void *target)
243 {
244 struct sig_handler *sh, *shb;
245
246 if (sig < 0 || sig >= MAX_SIGNAL)
247 return;
248
249 if (!target)
250 return;
251
252 list_for_each_entry_safe(sh, shb, &signal_state[sig].handlers, list) {
253 if (sh->handler == target) {
254 LIST_DELETE(&sh->list);
255 pool_free(pool_head_sig_handlers, sh);
256 break;
257 }
258 }
259 }
260
261 /*
262 * Immedialtely unregister every handler assigned to a signal <sig>.
263 * Once the handler list is empty, the signal is ignored with SIG_IGN.
264 */
265
signal_unregister(int sig)266 void signal_unregister(int sig)
267 {
268 struct sig_handler *sh, *shb;
269
270 if (sig < 0 || sig >= MAX_SIGNAL)
271 return;
272
273 list_for_each_entry_safe(sh, shb, &signal_state[sig].handlers, list) {
274 LIST_DELETE(&sh->list);
275 pool_free(pool_head_sig_handlers, sh);
276 }
277
278 signal(sig, SIG_IGN);
279 }
280
281 INITCALL0(STG_PREPARE, signal_init);
282