1 #include "declarations.h"
2 #include "sighand.h"
3
4 #if defined(PROG_HAS_DEBUG) && defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H)
5 #include <execinfo.h>
6 #endif
7
8
9
10 /* REMEMBER unlike here, signal handlers must not call aything but reentrant functions */
11
handler_bye_process(int n,__UNUSED__ siginfo_t * g,__UNUSED__ void * v)12 void handler_bye_process(int n, __UNUSED__ siginfo_t *g, __UNUSED__ void *v) {
13 /* Signal number is exit code */
14 (void) main_free(n);
15 }
16
handler_hup_process(int n,siginfo_t * g,void * v)17 void handler_hup_process(int n, siginfo_t *g, void *v) {
18 (void) flush_error();
19
20 LOGINFO(
21 ERROR_NOERROR, SUBSYSTEM,
22 _("Hangup signal received, %s will now stop"),
23 APPLICATION_NAME
24 );
25
26 (void) handler_trm_process(n, g, v);
27 }
28
handler_fpe_process(int n,siginfo_t * g,void * v)29 void handler_fpe_process(int n, siginfo_t *g, void *v) {
30 (void) flush_error();
31
32 LOGWARN(
33 ERROR_NOERROR, SUBSYSTEM,
34 _("Floating point exception %d occurred. %s will now stop. Thank you for your cooperation"),
35 n, APPLICATION_NAME
36 );
37
38 (void) handler_detail(g, v);
39 (void) handler_bye_process(n, g, v);
40 }
41
handler_ill_process(int n,siginfo_t * g,void * v)42 void handler_ill_process(int n, siginfo_t *g, void *v) {
43 (void) flush_error();
44
45 LOGWARN(
46 ERROR_NOERROR, SUBSYSTEM,
47 _("Illegal instruction exception %d occurred. %s will now stop. Thank you for your cooperation"),
48 n, APPLICATION_NAME
49 );
50
51 (void) handler_detail(g, v);
52 (void) handler_bye_process(n, g, v);
53 }
54 #if ! defined(PROG_HAS_DEBUG)
handler_seg_process(int n,siginfo_t * g,void * v)55 void handler_seg_process(int n, siginfo_t *g, void *v) {
56 (void) flush_error();
57
58 LOGWARN(
59 ERROR_NOERROR, SUBSYSTEM,
60 _("Segmentation fault %d occurred. %s will now stop. Thank you for your cooperation"),
61 n, APPLICATION_NAME
62 );
63
64 (void) handler_detail(g, v);
65 (void) handler_bye_process(n, g, v);
66 }
67 #endif
handler_trm_process(__UNUSED__ int n,__UNUSED__ siginfo_t * g,__UNUSED__ void * v)68 void handler_trm_process(__UNUSED__ int n, __UNUSED__ siginfo_t *g, __UNUSED__ void *v) {
69 (void) main_stop();
70 }
71
handler_inf_process(__UNUSED__ int n,__UNUSED__ siginfo_t * g,__UNUSED__ void * v)72 void handler_inf_process(__UNUSED__ int n, __UNUSED__ siginfo_t *g, __UNUSED__ void *v) {
73 (void) proc_times();
74 }
75
handler_detail(siginfo_t * g,void * v)76 static void handler_detail(siginfo_t *g, void *v) {
77 char *e;
78 #if ! defined(__OpenBSD__) && defined(HAVE_UCONTEXT_T)
79 ucontext_t *u;
80 #endif
81 (void) set_error(g->si_errno);
82
83 switch(g->si_signo) {
84 case SIGILL:
85 switch(g->si_code) {
86 case ILL_ILLOPC:
87 e = "Illegal opcode";
88
89 break;
90 case ILL_ILLOPN:
91 e = "Illegal operand";
92
93 break;
94 case ILL_ILLADR:
95 e = "Illegal addressing mode";
96
97 break;
98 case ILL_ILLTRP:
99 e = "Illegal trap";
100
101 break;
102 case ILL_PRVOPC:
103 e = "Illegal privileged opcode";
104
105 break;
106 case ILL_PRVREG:
107 e = "Illegal privileged register";
108
109 break;
110 case ILL_COPROC:
111 e = "Coprocessor error";
112
113 break;
114 case ILL_BADSTK:
115 e = "Internal stack error";
116
117 break;
118 default:
119 e = "Illegal instruction";
120
121 break;
122 }
123
124 LOGWARN(
125 ERROR_NOERROR, SUBSYSTEM,
126 _("%s: Failed address: %p"),
127 e, (void *) g->si_addr
128 );
129
130 break;
131 case SIGFPE:
132 switch(g->si_code) {
133 case FPE_INTDIV:
134 e = "Integer divide by zero";
135
136 break;
137 case FPE_INTOVF:
138 e = "Integer overflow";
139
140 break;
141 case FPE_FLTDIV:
142 e = "Floating point divide by zero";
143
144 break;
145 case FPE_FLTOVF:
146 e = "Floating point overflow";
147
148 break;
149 case FPE_FLTUND:
150 e = "Floating point underflow";
151
152 break;
153 case FPE_FLTRES:
154 e = "Floating point inexact result";
155
156 break;
157 case FPE_FLTINV:
158 e = "Invalid floating point operation";
159
160 break;
161 case FPE_FLTSUB:
162 e = "Subscript out of range";
163
164 break;
165 default:
166 e = "Floating point error";
167
168 break;
169 }
170
171 LOGWARN(
172 ERROR_NOERROR, SUBSYSTEM,
173 _("%s: Failed address: %p"),
174 e, (void *) g->si_addr
175 );
176
177 break;
178 case SIGSEGV:
179 switch(g->si_code) {
180 case SEGV_MAPERR:
181 e = "Address not mapped to object";
182
183 break;
184 case SEGV_ACCERR:
185 e = "Invalid permissions for mapped object";
186
187 break;
188 default:
189 e = "Segmentation fault";
190
191 break;
192 }
193
194 LOGWARN(
195 ERROR_NOERROR, SUBSYSTEM,
196 _("%s: Failed address: %p"),
197 e, (void *) g->si_addr
198 );
199
200 break;
201 case SIGBUS:
202 switch(g->si_code) {
203 case BUS_ADRALN:
204 e = "Invalid address alignment";
205
206 break;
207 case BUS_ADRERR:
208 e = "Nonexistent physical address";
209
210 break;
211 case BUS_OBJERR:
212 e = "Object-specific hardware error";
213
214 break;
215 default:
216 e = "Bus error";
217
218 break;
219 }
220
221 LOGWARN(
222 ERROR_NOERROR, SUBSYSTEM,
223 _("%s: Failed address: %p"),
224 e, (void *) g->si_addr
225 );
226
227 break;
228 #if ! defined(PROG_HAS_DEBUG)
229 case SIGTRAP:
230 switch(g->si_code) {
231 #if defined(TRAP_BRKPT)
232 case TRAP_BRKPT:
233 e = "Process breakpoint";
234
235 break;
236 #endif
237 #if defined(TRAP_TRACE)
238 case TRAP_TRACE:
239 e = "Process trace trap";
240
241 break;
242 #endif
243 default:
244 e = "Process trap";
245
246 break;
247 }
248
249 LOGWARN(
250 ERROR_NOERROR, SUBSYSTEM,
251 _("%s"),
252 e
253 );
254
255 break;
256 #endif
257 case SIGCHLD:
258 switch(g->si_code) {
259 case CLD_EXITED:
260 e = "Child has exited";
261
262 break;
263 case CLD_KILLED:
264 e = "Child has terminated abnormally and did not create a core file";
265
266 break;
267 case CLD_DUMPED:
268 e = "Child has terminated abnormally and created a core file";
269
270 break;
271 #if ! defined(PROG_HAS_DEBUG)
272 case CLD_TRAPPED:
273 e = "Traced child has trapped";
274
275 break;
276 #endif
277 case CLD_STOPPED:
278 e = "Child has stopped";
279
280 break;
281 case CLD_CONTINUED:
282 e = "Stopped child has continued";
283
284 break;
285 default:
286 e = "Child error";
287
288 break;
289 }
290
291 LOGWARN(
292 ERROR_NOERROR, SUBSYSTEM,
293 _("%s: Child pid %ld, euid %ld, exit code %d"),
294 e, (long) g->si_pid, (long) g->si_uid, g->si_status
295 );
296
297 break;
298 case SIGIO:
299 switch(g->si_code) {
300 #if defined(POLL_IN)
301 case POLL_IN:
302 e = "Data input available";
303
304 break;
305 #endif
306 #if defined(POLL_OUT)
307 case POLL_OUT:
308 e = "Output buffers available";
309
310 break;
311 #endif
312 #if defined(POLL_MSG)
313 case POLL_MSG:
314 e = "Input message available";
315
316 break;
317 #endif
318 #if defined(POLL_ERR)
319 case POLL_ERR:
320 e = "I/O error";
321
322 break;
323 #endif
324 #if defined(POLL_PRI)
325 case POLL_PRI:
326 e = "High priority input available";
327
328 break;
329 #endif
330 #if defined(POLL_HUP)
331 case POLL_HUP:
332 e = "Device disconnected";
333
334 break;
335 #endif
336 default:
337 e = "I/O error";
338
339 break;
340 }
341 #if defined(__OpenBSD__) || defined(__CYGWIN__)
342 LOGWARN(
343 ERROR_NOERROR, SUBSYSTEM,
344 _("%s"),
345 e
346 );
347 #else
348 LOGWARN(
349 ERROR_NOERROR, SUBSYSTEM,
350 _("%s: Band event: %d"),
351 e, g->si_band
352 );
353 #endif
354 break;
355 #if defined(SIGSTKFLT)
356 case SIGSTKFLT:
357 LOGWARN(
358 ERROR_NOERROR, SUBSYSTEM,
359 _("Stack fault")
360 );
361
362 break;
363 #endif
364 case SIGXCPU:
365 LOGWARN(
366 ERROR_NOERROR, SUBSYSTEM,
367 _("CPU limit exceeded")
368 );
369
370 break;
371 case SIGXFSZ:
372 LOGWARN(
373 ERROR_NOERROR, SUBSYSTEM,
374 _("File size limit exceeded")
375 );
376
377 break;
378 default:
379 break;
380 }
381 #if ! defined(__OpenBSD__) && defined(HAVE_UCONTEXT_T)
382 u = (ucontext_t *) v;
383
384 if(u->uc_stack.ss_size != 0) {
385 LOGWARN(
386 ERROR_NOERROR, SUBSYSTEM,
387 _("Process stack size is %lu bytes, base at address %p"),
388 (unsigned long) u->uc_stack.ss_size, u->uc_stack.ss_sp
389 );
390 }
391 #else
392 (void) v;
393 #endif
394 (void) handler_stack_print();
395 }
396
handler_stack_print(void)397 void handler_stack_print(void) {
398 #if defined(PROG_HAS_DEBUG) && defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H)
399 char **s;
400
401 void *a[STACK_FRAME_MAX];
402
403 size_t i, t;
404
405 if((t = backtrace(a, STACK_FRAME_MAX)) == 0) return;
406 if((s = backtrace_symbols(a, t)) == NULL) return;
407
408 (void) flush_error();
409
410 LOGWARN(
411 ERROR_NOERROR, SUBSYSTEM,
412 _("Dumping stack frame, %lu entries below"),
413 (unsigned long) t
414 );
415
416 (void) fflush(stdout);
417 (void) fflush(stderr);
418
419 for(i = 0; i < t; i++) (void) fprintf(stderr, "%.2zu: %s%c", i, s[i], CONFIG_LINE_FEED);
420
421 (void) free(s);
422 #endif
423 }
424