summaryrefslogtreecommitdiffstats
path: root/base/all/root/scripts/setup_segv_handler.sh
blob: 763f22d3854596f7e9dc78a0209382931bd389d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/bin/bash
# a script to setup a segmentation fault handler on a SoFS cluster
# tridge@samba.org July 2008

set -e

echo "Creating source file"
mkdir -p /usr/local/src

cat <<EOFSOURCE > /usr/local/src/segv_handler.c
#define _GNU_SOURCE
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>

static int segv_handler(int sig)
{
	char cmd[100];
	char progname[100];	
	char *p;
	int n;

	n = readlink("/proc/self/exe",progname,sizeof(progname));
	progname[n] = 0;

	p = strrchr(progname, '/');
	*p = 0;
	
	snprintf(cmd, sizeof(cmd), "/usr/local/bin/backtrace %d 2>&1 | tee /var/log/segv/segv_%s.%d.out > /dev/console", 
		 (int)getpid(), p+1, (int)getpid());
	system(cmd);
	signal(SIGSEGV, SIG_DFL);
	return 0;
}

static void segv_init() __attribute__((constructor));
void segv_init(void)
{
	signal(SIGSEGV, (sighandler_t) segv_handler);
	signal(SIGBUS, (sighandler_t) segv_handler);
}
EOFSOURCE

mkdir -p /usr/local/bin
cat <<EOFSOURCE > /usr/local/bin/backtrace
#!/bin/sh

# we want everything on stderr, so the program is not disturbed
exec 1>&2

PID=\$1
TMPFILE=/tmp/gdb.\$\$
cat << EOF  > \$TMPFILE
set height 0
bt full
thread apply all bt full
quit
EOF
gdb -batch -x \$TMPFILE --pid \$PID < /dev/null 
/bin/rm -f \$TMPFILE

EOFSOURCE

chmod +x /usr/local/bin/backtrace

mkdir -p /var/log/segv

echo "Compiling 64 bit shared library"
mkdir -p /usr/local/lib
gcc -m64 -shared -fPIC -o /usr/local/lib/segv_handler64.so /usr/local/src/segv_handler.c

echo "Compiling 32 bit shared library"
mkdir -p /usr/local/lib
gcc -m32 -shared -fPIC -o /usr/local/lib/segv_handler32.so /usr/local/src/segv_handler.c

echo "Modifying /lib/ld-2.5.so for LD_PRELO32"
sed -e 's@/etc/ld.so.preload@/etc/ld.so.prelo32@g' -i.orig /lib/ld-2.5.so
# we need to remove the original to stop ldconfig enabling it
rm -f /lib/ld-2.5.so.orig

echo "Creating /etc/ld.so.prelo32"
echo "/usr/local/lib/segv_handler32.so" > /etc/ld.so.prelo32

echo "Creating /etc/ld.so.preload"
echo "/usr/local/lib/segv_handler64.so" >> /etc/ld.so.preload
sort -u < /etc/ld.so.preload > /etc/ld.so.preload.$$
mv /etc/ld.so.preload.$$ /etc/ld.so.preload

echo "Copying install to other nodes"
onnode -p all rsync $HOSTNAME:/usr/local/bin/backtrace /usr/local/bin/
onnode -p all rsync $HOSTNAME:/usr/local/lib/segv_handler*so /usr/local/lib
onnode -p all rsync $HOSTNAME:/etc/ld.so.preload /etc/
onnode -p all rsync $HOSTNAME:/etc/ld.so.prelo32 /etc/
onnode -p all rsync $HOSTNAME:/lib/ld-2.5.so /lib/
onnode -p all mkdir -p /var/log/segv
onnode -p all chmod a+rwx /var/log/segv

cat <<EOF
segv_handler installed. To take full effect you must restart your daemons
or reboot
EOF