1
/* sigsegv.c -- sigsegv handlers
3
* Copyright (c) 2003 Juan F. Codagnone <juam@users.sourceforge.net>
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice shall be included
13
* in all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36
#ifdef HAVE_PTHREADS_H
41
* http://www.gnu.org/manual/glibc-2.2.3/html_chapter/libc_33.html
43
#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1
44
# define HAVE_BACKTRACE
45
# include <execinfo.h>
49
#include "crash_sigsegv.h"
53
static int (* print)(const char *format, ...) = NULL;
54
static int needs_cr = 1;
56
void *sigsegv_set_print( int (* fnc)(const char *format, ...), int _needs_cr)
68
* launchs gdb, and feeds myprint with the backtrace
70
static int dump_pid_son(pid_t pid, const char *binary, int full_bt,
71
int (* myprint)(const char *format, ...))
73
char tmp[]="/tmp/mrbug-crash-XXXXXX";
80
(*myprint)("opening gdb command (tempory) file `%s'%s", tmp,
81
needs_cr ? "\n" : "");
86
char gdb_cmd[]="bt\nquit";
87
char gdb_cmd_full[]="bt full\nquit";
92
write(fd, gdb_cmd_full, strlen(gdb_cmd_full));
94
write(fd, gdb_cmd, strlen(gdb_cmd));
97
sprintf(cmd, "gdb -nw -n -batch -x \"%s\" %s %d", tmp, binary,
99
(*myprint)("trying to dump pid: %d (%s)...%s", pid, binary,
100
needs_cr ? "\n" : "");
103
fp = popen(cmd, "r");
106
(*myprint)("err. couldn't exec `%s'%s", cmd,
107
needs_cr ? "\n" : "");
115
while(fgets(buff, sizeof(buff), fp))
118
if( buff[len-1] == '\n')
121
(*myprint)("%s%s", buff,needs_cr ? "\n" : "");
125
if( remove(tmp) == -1 )
126
(*myprint)("removing `%s` (@;@)%s", tmp,
127
needs_cr ? "\n" : "");
133
static int dump_pid(pid_t pid, const char *binary, int full_bt )
136
int (* myprint)(const char *format, ...);
138
myprint = print ? (int(*)(const char *format, ...))print : (int(*)(const char *format, ...))printf;
141
* clone the process, so we don't make the bt bigger.
146
dump_pid_son(pid, binary, full_bt, myprint);
149
else if( mpid == -1 )
150
(*myprint)("lunching son: `%s' %s", strerror(errno),
151
needs_cr ? "\n" : "");
158
waitpid(0, &status, 0);
159
if( WIFEXITED(status) && WEXITSTATUS(status)==0 )
167
* get `pid`'s real path
169
* \param buff buffer for the output
170
* \param nbuff size of the buffer
171
* \param pid pid processes id to use
173
* \note this function works only in linux
177
static char *get_path_from_pid(char *buff, size_t nbuff, pid_t pid)
183
sprintf(proc, "/proc/%d/exe", pid);
184
if( (n=readlink(proc, buff, nbuff)) == -1 )
195
static void sigsegv_libc_dump( int (* myprint)(const char *format, ...) )
197
void *array[48] = {0};
202
#ifdef HAVE_BACKTRACE
203
(*myprint)("Backtrace:%c", needs_cr ? "\n" : "");
204
n = backtrace(array, sizeof(array)/(sizeof(*array)));
205
res = backtrace_symbols(array, n);
206
for (i = 0; i < n; i++)
207
(*myprint)("%s%s", res[i], needs_cr ? "\n" : "");
209
(*myprint)("Attempting to generate core file%s",
214
static void sigsegv_handler_generic(int signal, int full_bt)
218
int (* myprint)(const char *format, ...);
220
myprint = print ? print : printf;
221
if( get_path_from_pid(binary, sizeof(binary), pid) == NULL)
222
(*myprint)("pid %d does not seems to exist", pid);
225
(*myprint)("Segmentation Violation Detected.%s",
226
needs_cr ? "\n" : "");
227
dump_pid(pid, binary, full_bt);
228
sigsegv_libc_dump(myprint);
231
#ifdef HAVE_PTHREAD_H
232
pthread_kill_other_threads_np();
238
void sigsegv_handler_fnc(int signal)
240
sigsegv_handler_generic(signal, 0);
243
void sigsegv_handler_bt_full_fnc(int signal)
245
sigsegv_handler_generic(signal, 1);
248
}; // namespace Crash