summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-11-05 17:00:03 -0500
committerTavian Barnes <tavianator@gmail.com>2009-11-05 17:00:03 -0500
commit69501590eec9c1bc6c7640d17b01ad4d2ce007a5 (patch)
tree925e1d55720631133584c781ef387d7e577fae5c
parentfc93aba423c69eddbb69a15d8e90f2272759cd62 (diff)
downloaddimension-69501590eec9c1bc6c7640d17b01ad4d2ce007a5.tar.xz
Make default fatal error handler nicer.
If we can, only exit the current thread, and print a backtrace.
-rw-r--r--libdimension/error.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/libdimension/error.c b/libdimension/error.c
index da7b8bd..c3c9b60 100644
--- a/libdimension/error.c
+++ b/libdimension/error.c
@@ -18,10 +18,15 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h> /* For gettid() where supported */
+#include <execinfo.h> /* For backtrace() etc. */
+
#include "dimension.h"
#include <pthread.h>
-#include <stdio.h> /* For fprintf() */
-#include <stdlib.h> /* For exit() */
+#include <stdio.h> /* For fprintf() */
+#include <stdlib.h> /* For exit() */
static void dmnsn_default_fatal_error_fn();
static dmnsn_fatal_error_fn *dmnsn_fatal = &dmnsn_default_fatal_error_fn;
@@ -131,5 +136,25 @@ void dmnsn_set_fatal_error_fn(dmnsn_fatal_error_fn *fatal)
static void
dmnsn_default_fatal_error_fn()
{
+ const unsigned int size = 64;
+ void *buffer[size];
+
+ int nptrs = backtrace(buffer, size);
+ /* buffer + 1 to hide this static function */
+ backtrace_symbols_fd(buffer + 1, nptrs - 1, STDERR_FILENO);
+
+#ifdef SYS_gettid
+ pid_t pid = getpid(),
+ tid = syscall(SYS_gettid);
+
+ if (pid == tid) {
+ exit(EXIT_FAILURE);
+ } else {
+ int *ret = malloc(sizeof(int));
+ *ret = 1;
+ pthread_exit(ret);
+ }
+#else
exit(EXIT_FAILURE);
+#endif
}