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