summaryrefslogtreecommitdiff
path: root/source4/lib/fault.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2004-06-30 19:46:28 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:56:50 -0500
commit1cec0de9273d10847ffb513679f6643a7a4cc648 (patch)
treee4a0ee47c04140ac1a0a7baacd2fcb51586e763b /source4/lib/fault.c
parentadf0d519a546085ee23a59d7284c443dc2321544 (diff)
downloadsamba-1cec0de9273d10847ffb513679f6643a7a4cc648.tar.gz
samba-1cec0de9273d10847ffb513679f6643a7a4cc648.tar.bz2
samba-1cec0de9273d10847ffb513679f6643a7a4cc648.zip
r1308: move smb_panic() to lib/fault.c
merge the backtrace stuff from 3.0 metze (This used to be commit 4daf1bafc71cc8f13188aeb85d81aa7513d57d95)
Diffstat (limited to 'source4/lib/fault.c')
-rw-r--r--source4/lib/fault.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/source4/lib/fault.c b/source4/lib/fault.c
index 47a43bca84..0ce003a2b0 100644
--- a/source4/lib/fault.c
+++ b/source4/lib/fault.c
@@ -29,6 +29,105 @@ static struct {
} fault_handlers;
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#define BACKTRACE_STACK_SIZE 64
+#elif HAVE_LIBEXC_H
+#include <libexc.h>
+#endif
+
+static void call_backtrace(void)
+{
+#ifdef HAVE_BACKTRACE
+#define BACKTRACE_STACK_SIZE 64
+ void *backtrace_stack[BACKTRACE_STACK_SIZE];
+ size_t backtrace_size;
+ char **backtrace_strings;
+
+ /* get the backtrace (stack frames) */
+ backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
+ backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
+
+ DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
+ (unsigned long)backtrace_size));
+
+ if (backtrace_strings) {
+ int i;
+
+ for (i = 0; i < backtrace_size; i++)
+ DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
+
+ /* Leak the backtrace_strings, rather than risk what free() might do */
+ }
+
+#elif HAVE_LIBEXC
+
+#define NAMESIZE 32 /* Arbitrary */
+
+ /* The IRIX libexc library provides an API for unwinding the stack. See
+ * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
+ * since we are about to abort anyway, it hardly matters.
+ *
+ * Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this
+ * will fail with a nasty message upon failing to open the /proc entry.
+ */
+ {
+ uint64_t addrs[BACKTRACE_STACK_SIZE];
+ char * names[BACKTRACE_STACK_SIZE];
+ char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
+
+ int i;
+ int levels;
+
+ ZERO_ARRAY(addrs);
+ ZERO_ARRAY(names);
+ ZERO_ARRAY(namebuf);
+
+ for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
+ names[i] = namebuf + (i * NAMESIZE);
+ }
+
+ levels = trace_back_stack(0, addrs, names,
+ BACKTRACE_STACK_SIZE, NAMESIZE);
+
+ DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
+ for (i = 0; i < levels; i++) {
+ DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
+ }
+ }
+#undef NAMESIZE
+#endif
+}
+
+/*******************************************************************
+ Something really nasty happened - panic !
+********************************************************************/
+void smb_panic(const char *why)
+{
+ const char *cmd = lp_panic_action();
+ int result;
+
+ if (cmd && *cmd) {
+ DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
+ result = system(cmd);
+
+ if (result == -1)
+ DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
+ strerror(errno)));
+ else
+ DEBUG(0, ("smb_panic(): action returned status %d\n",
+ WEXITSTATUS(result)));
+ }
+ DEBUG(0,("PANIC: %s\n", why));
+
+ call_backtrace();
+
+#ifdef SIGABRT
+ CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
+#endif
+ abort();
+}
+
/*******************************************************************
report a fault
********************************************************************/
@@ -53,6 +152,9 @@ static void fault_report(int sig)
#ifdef SIGBUS
CatchSignal(SIGBUS,SIGNAL_CAST SIG_DFL);
#endif
+#ifdef SIGABRT
+ CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
+#endif
return; /* this should cause a core dump */
}
exit(1);
@@ -84,6 +186,9 @@ void fault_setup(void (*fn)(void *))
#ifdef SIGBUS
CatchSignal(SIGBUS,SIGNAL_CAST sig_fault);
#endif
+#ifdef SIGABRT
+ CatchSignal(SIGABRT,SIGNAL_CAST sig_fault);
+#endif
}
/*