summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/build/m4/rewrite.m42
-rw-r--r--source4/lib/fault.c105
-rw-r--r--source4/lib/util.c24
3 files changed, 106 insertions, 25 deletions
diff --git a/source4/build/m4/rewrite.m4 b/source4/build/m4/rewrite.m4
index bd29d03c1f..05687f78ec 100644
--- a/source4/build/m4/rewrite.m4
+++ b/source4/build/m4/rewrite.m4
@@ -413,7 +413,7 @@ AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups sysconf mktime rename ftruncate
AC_CHECK_FUNCS(lstat64 fopen64 atexit grantpt dup2 lseek64 ftruncate64 readdir64)
AC_CHECK_FUNCS(fseek64 fseeko64 ftell64 ftello64 setluid getpwanam setlinebuf)
AC_CHECK_FUNCS(srandom random srand rand setenv usleep strcasecmp fcvt fcvtl symlink readlink)
-AC_CHECK_FUNCS(syslog vsyslog getgrouplist timegm)
+AC_CHECK_FUNCS(syslog vsyslog getgrouplist timegm backtrace)
# setbuffer, shmget, shm_open are needed for smbtorture
AC_CHECK_FUNCS(setbuffer shmget shm_open)
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
}
/*
diff --git a/source4/lib/util.c b/source4/lib/util.c
index ee637aeaad..3b23543bfc 100644
--- a/source4/lib/util.c
+++ b/source4/lib/util.c
@@ -562,30 +562,6 @@ gid_t nametogid(const char *name)
return (gid_t)-1;
}
-/*******************************************************************
- 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));
- abort();
-}
-
/****************************************************************************
Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
is dealt with in posix.c