1 /* -*- linux-c -*- */
2 
3 /* Taken from
4  * http://tlug.up.ac.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV
5  * and tailored to Aqualung.
6  */
7 
8 /* $Id: segv.c 1245 2012-02-04 10:33:30Z assworth $ */
9 
10 #include <config.h>
11 
12 #include <stddef.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <signal.h>
17 
18 #ifdef DEBUG_BUILD
19 
20 #include <execinfo.h>
21 
22 #include "version.h"
23 
24 #endif /* DEBUG_BUILD */
25 
26 #include "segv.h"
27 
28 
29 #ifdef DEBUG_BUILD
30 static void
signal_segv(int signum,siginfo_t * info,void * ptr)31 signal_segv(int signum, siginfo_t * info, void * ptr) {
32 
33 	unsigned i;
34 	void *bt[20];
35 	char **strings;
36 	size_t sz;
37 
38 	fprintf(stderr, "===[ Aqualung %s CRASH REPORT ]===\n", AQUALUNG_VERSION);
39 #ifdef HAVE_PSIGINFO
40 	psiginfo(info, "Caught");
41 #else
42 	psignal(signum, "Caught");
43 #endif
44 	fprintf(stderr, "Please mail this to <aqualung-friends@lists.sourceforge.net>\n");
45 	fprintf(stderr, "along with a short description of what you were doing when\n");
46 	fprintf(stderr, "the program crashed. Please also send the output of `aqualung -v'.\n");
47 	fprintf(stderr, "Thank you in advance!\n");
48 
49 	sz = backtrace(bt, 20);
50 	strings = backtrace_symbols(bt, sz);
51 
52 	fprintf(stderr, "\nbacktrace (%zd stack frames)\n", sz);
53 	for(i = 0; i < sz; ++i)
54 		fprintf(stderr, "%s\n", strings[i]);
55 	fprintf(stderr, "===[ END OF CRASH REPORT ]===\n");
56 
57 	free(strings);
58 	exit (-1);
59 }
60 #endif /* DEBUG_BUILD */
61 
62 #ifdef RELEASE_BUILD
63 static void
signal_segv(int signum,siginfo_t * info,void * ptr)64 signal_segv(int signum, siginfo_t * info, void * ptr) {
65 
66 	fprintf(stderr, "Aqualung received signal %d (%s).\n\n",
67 		signum, strsignal(signum));
68 #ifndef _WIN32
69 	fprintf(stderr, "To help the developers fix the bug causing this crash,\n");
70 	fprintf(stderr, "please do the following:\n\n");
71 	fprintf(stderr, "1) configure & make Aqualung with --enable-debug\n");
72 	fprintf(stderr, "2) reproduce the crash\n");
73 	fprintf(stderr, "3) send the crash report to the developers\n\n");
74 	fprintf(stderr, "Thank you for supporting Aqualung!\n");
75 #endif /* !_WIN32 */
76 	exit(-1);
77 }
78 #endif /* RELEASE_BUILD */
79 
80 int
setup_sigsegv()81 setup_sigsegv() {
82 	struct sigaction action;
83 	memset(&action, 0, sizeof(action));
84 	action.sa_sigaction = signal_segv;
85 	action.sa_flags = SA_SIGINFO;
86 
87 	if (sigaction(SIGFPE, &action, NULL) < 0) {
88 		perror("sigaction");
89 		return 0;
90 	}
91 	if (sigaction(SIGILL, &action, NULL) < 0) {
92 		perror("sigaction");
93 		return 0;
94 	}
95 	if (sigaction(SIGSEGV, &action, NULL) < 0) {
96 		perror("sigaction");
97 		return 0;
98 	}
99 	if (sigaction(SIGBUS, &action, NULL) < 0) {
100 		perror("sigaction");
101 		return 0;
102 	}
103 	if (sigaction(SIGABRT, &action, NULL) < 0) {
104 		perror("sigaction");
105 		return 0;
106 	}
107 	return 1;
108 }
109 
110 #ifndef SIGSEGV_NO_AUTO_INIT
111 static void
112 __attribute((constructor))
init(void)113 init(void) {
114 	setup_sigsegv();
115 }
116 #endif
117 
118 // vim: shiftwidth=8:tabstop=8:softtabstop=8 :
119 
120