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