763f22d3854596f7e9dc78a0209382931bd389d4
[autocluster.git] / base / all / root / scripts / setup_segv_handler.sh
1 #!/bin/bash
2 # a script to setup a segmentation fault handler on a SoFS cluster
3 # tridge@samba.org July 2008
4
5 set -e
6
7 echo "Creating source file"
8 mkdir -p /usr/local/src
9
10 cat <<EOFSOURCE > /usr/local/src/segv_handler.c
11 #define _GNU_SOURCE
12 #include <signal.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <dlfcn.h>
18
19 static int segv_handler(int sig)
20 {
21         char cmd[100];
22         char progname[100];     
23         char *p;
24         int n;
25
26         n = readlink("/proc/self/exe",progname,sizeof(progname));
27         progname[n] = 0;
28
29         p = strrchr(progname, '/');
30         *p = 0;
31         
32         snprintf(cmd, sizeof(cmd), "/usr/local/bin/backtrace %d 2>&1 | tee /var/log/segv/segv_%s.%d.out > /dev/console", 
33                  (int)getpid(), p+1, (int)getpid());
34         system(cmd);
35         signal(SIGSEGV, SIG_DFL);
36         return 0;
37 }
38
39 static void segv_init() __attribute__((constructor));
40 void segv_init(void)
41 {
42         signal(SIGSEGV, (sighandler_t) segv_handler);
43         signal(SIGBUS, (sighandler_t) segv_handler);
44 }
45 EOFSOURCE
46
47 mkdir -p /usr/local/bin
48 cat <<EOFSOURCE > /usr/local/bin/backtrace
49 #!/bin/sh
50
51 # we want everything on stderr, so the program is not disturbed
52 exec 1>&2
53
54 PID=\$1
55 TMPFILE=/tmp/gdb.\$\$
56 cat << EOF  > \$TMPFILE
57 set height 0
58 bt full
59 thread apply all bt full
60 quit
61 EOF
62 gdb -batch -x \$TMPFILE --pid \$PID < /dev/null 
63 /bin/rm -f \$TMPFILE
64
65 EOFSOURCE
66
67 chmod +x /usr/local/bin/backtrace
68
69 mkdir -p /var/log/segv
70
71 echo "Compiling 64 bit shared library"
72 mkdir -p /usr/local/lib
73 gcc -m64 -shared -fPIC -o /usr/local/lib/segv_handler64.so /usr/local/src/segv_handler.c
74
75 echo "Compiling 32 bit shared library"
76 mkdir -p /usr/local/lib
77 gcc -m32 -shared -fPIC -o /usr/local/lib/segv_handler32.so /usr/local/src/segv_handler.c
78
79 echo "Modifying /lib/ld-2.5.so for LD_PRELO32"
80 sed -e 's@/etc/ld.so.preload@/etc/ld.so.prelo32@g' -i.orig /lib/ld-2.5.so
81 # we need to remove the original to stop ldconfig enabling it
82 rm -f /lib/ld-2.5.so.orig
83
84 echo "Creating /etc/ld.so.prelo32"
85 echo "/usr/local/lib/segv_handler32.so" > /etc/ld.so.prelo32
86
87 echo "Creating /etc/ld.so.preload"
88 echo "/usr/local/lib/segv_handler64.so" >> /etc/ld.so.preload
89 sort -u < /etc/ld.so.preload > /etc/ld.so.preload.$$
90 mv /etc/ld.so.preload.$$ /etc/ld.so.preload
91
92 echo "Copying install to other nodes"
93 onnode -p all rsync $HOSTNAME:/usr/local/bin/backtrace /usr/local/bin/
94 onnode -p all rsync $HOSTNAME:/usr/local/lib/segv_handler*so /usr/local/lib
95 onnode -p all rsync $HOSTNAME:/etc/ld.so.preload /etc/
96 onnode -p all rsync $HOSTNAME:/etc/ld.so.prelo32 /etc/
97 onnode -p all rsync $HOSTNAME:/lib/ld-2.5.so /lib/
98 onnode -p all mkdir -p /var/log/segv
99 onnode -p all chmod a+rwx /var/log/segv
100
101 cat <<EOF
102 segv_handler installed. To take full effect you must restart your daemons
103 or reboot
104 EOF