This source file includes following definitions.
- init_fatal_signals
- uninstall_handlers
- fatal_signal_handler
- install_handlers
- gl_lock_define_initialized
- do_init_fatal_signal_set
- gl_once_define
- block_fatal_signals
- unblock_fatal_signals
- get_fatal_signals
- get_fatal_signal_set
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include "fatal-signal.h"
23
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <unistd.h>
28
29 #include "glthread/lock.h"
30 #include "thread-optim.h"
31 #include "sig-handler.h"
32
33 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 static int fatal_signals[] =
53 {
54
55 #ifdef SIGINT
56 SIGINT,
57 #endif
58 #ifdef SIGTERM
59 SIGTERM,
60 #endif
61
62 #ifdef SIGHUP
63 SIGHUP,
64 #endif
65 #ifdef SIGPIPE
66 SIGPIPE,
67 #endif
68
69 #ifdef SIGXCPU
70 SIGXCPU,
71 #endif
72 #ifdef SIGXFSZ
73 SIGXFSZ,
74 #endif
75
76 #ifdef SIGBREAK
77 SIGBREAK,
78 #endif
79 0
80 };
81
82 #define num_fatal_signals (SIZEOF (fatal_signals) - 1)
83
84
85
86 static void
87 init_fatal_signals (void)
88 {
89
90
91
92
93 static bool fatal_signals_initialized = false;
94 if (!fatal_signals_initialized)
95 {
96 size_t i;
97
98 for (i = 0; i < num_fatal_signals; i++)
99 {
100 struct sigaction action;
101
102 if (sigaction (fatal_signals[i], NULL, &action) >= 0
103 && get_handler (&action) == SIG_IGN)
104 fatal_signals[i] = -1;
105 }
106
107 fatal_signals_initialized = true;
108 }
109 }
110
111
112
113
114
115 typedef _GL_ASYNC_SAFE void (*action_t) (int sig);
116
117
118
119
120 typedef struct
121 {
122 volatile action_t action;
123 }
124 actions_entry_t;
125
126
127 static actions_entry_t static_actions[32];
128 static actions_entry_t * volatile actions = static_actions;
129 static sig_atomic_t volatile actions_count = 0;
130 static size_t actions_allocated = SIZEOF (static_actions);
131
132
133
134
135 static struct sigaction saved_sigactions[64];
136
137
138
139 static _GL_ASYNC_SAFE void
140 uninstall_handlers (void)
141 {
142 size_t i;
143
144 for (i = 0; i < num_fatal_signals; i++)
145 if (fatal_signals[i] >= 0)
146 {
147 int sig = fatal_signals[i];
148 if (saved_sigactions[sig].sa_handler == SIG_IGN)
149 saved_sigactions[sig].sa_handler = SIG_DFL;
150 sigaction (sig, &saved_sigactions[sig], NULL);
151 }
152 }
153
154
155
156 static _GL_ASYNC_SAFE void
157 fatal_signal_handler (int sig)
158 {
159 for (;;)
160 {
161
162 action_t action;
163 size_t n = actions_count;
164 if (n == 0)
165 break;
166 n--;
167 actions_count = n;
168 action = actions[n].action;
169
170 action (sig);
171 }
172
173
174
175
176
177
178 uninstall_handlers ();
179 raise (sig);
180 }
181
182
183
184 static void
185 install_handlers (void)
186 {
187 size_t i;
188 struct sigaction action;
189
190 action.sa_handler = &fatal_signal_handler;
191
192
193
194 action.sa_flags = SA_NODEFER;
195 sigemptyset (&action.sa_mask);
196 for (i = 0; i < num_fatal_signals; i++)
197 if (fatal_signals[i] >= 0)
198 {
199 int sig = fatal_signals[i];
200
201 if (!(sig < sizeof (saved_sigactions) / sizeof (saved_sigactions[0])))
202 abort ();
203 sigaction (sig, &action, &saved_sigactions[sig]);
204 }
205 }
206
207
208
209 gl_lock_define_initialized (static, at_fatal_signal_lock)
210
211
212
213 int
214 at_fatal_signal (action_t action)
215 {
216 bool mt = gl_multithreaded ();
217
218 if (mt) gl_lock_lock (at_fatal_signal_lock);
219
220 static bool cleanup_initialized = false;
221 if (!cleanup_initialized)
222 {
223 init_fatal_signals ();
224 install_handlers ();
225 cleanup_initialized = true;
226 }
227
228 int ret = 0;
229
230 if (actions_count == actions_allocated)
231 {
232
233
234
235 actions_entry_t *old_actions = actions;
236 size_t old_actions_allocated = actions_allocated;
237 size_t new_actions_allocated = 2 * actions_allocated;
238 actions_entry_t *new_actions =
239 (actions_entry_t *)
240 malloc (new_actions_allocated * sizeof (actions_entry_t));
241 if (new_actions == NULL)
242 {
243 ret = -1;
244 goto done;
245 }
246
247 size_t k;
248
249
250
251 for (k = 0; k < old_actions_allocated; k++)
252 new_actions[k] = old_actions[k];
253 actions = new_actions;
254 actions_allocated = new_actions_allocated;
255
256
257
258
259
260
261 #if 0
262 if (old_actions != static_actions)
263 free (old_actions);
264 #endif
265 }
266
267
268
269
270 actions[actions_count].action = action;
271 actions_count++;
272
273 done:
274 if (mt) gl_lock_unlock (at_fatal_signal_lock);
275
276 return ret;
277 }
278
279
280
281
282
283 static sigset_t fatal_signal_set;
284
285 static void
286 do_init_fatal_signal_set (void)
287 {
288 size_t i;
289
290 init_fatal_signals ();
291
292 sigemptyset (&fatal_signal_set);
293 for (i = 0; i < num_fatal_signals; i++)
294 if (fatal_signals[i] >= 0)
295 sigaddset (&fatal_signal_set, fatal_signals[i]);
296 }
297
298
299 gl_once_define(static, fatal_signal_set_once)
300
301 static void
302 init_fatal_signal_set (void)
303 {
304 gl_once (fatal_signal_set_once, do_init_fatal_signal_set);
305 }
306
307
308
309 gl_lock_define_initialized (static, fatal_signals_block_lock)
310 static unsigned int fatal_signals_block_counter = 0;
311
312
313 void
314 block_fatal_signals (void)
315 {
316 bool mt = gl_multithreaded ();
317
318 if (mt) gl_lock_lock (fatal_signals_block_lock);
319
320 if (fatal_signals_block_counter++ == 0)
321 {
322 init_fatal_signal_set ();
323 sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
324 }
325
326 if (mt) gl_lock_unlock (fatal_signals_block_lock);
327 }
328
329
330 void
331 unblock_fatal_signals (void)
332 {
333 bool mt = gl_multithreaded ();
334
335 if (mt) gl_lock_lock (fatal_signals_block_lock);
336
337 if (fatal_signals_block_counter == 0)
338
339
340 abort ();
341 if (--fatal_signals_block_counter == 0)
342 {
343 init_fatal_signal_set ();
344 sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
345 }
346
347 if (mt) gl_lock_unlock (fatal_signals_block_lock);
348 }
349
350
351 unsigned int
352 get_fatal_signals (int signals[64])
353 {
354 init_fatal_signal_set ();
355
356 {
357 int *p = signals;
358 size_t i;
359
360 for (i = 0; i < num_fatal_signals; i++)
361 if (fatal_signals[i] >= 0)
362 *p++ = fatal_signals[i];
363 return p - signals;
364 }
365 }
366
367 const sigset_t *
368 get_fatal_signal_set (void)
369 {
370 init_fatal_signal_set ();
371 return &fatal_signal_set;
372 }