diff options
author | Tavian Barnes <tavianator@gmail.com> | 2009-11-05 17:00:03 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2009-11-05 17:00:03 -0500 |
commit | 69501590eec9c1bc6c7640d17b01ad4d2ce007a5 (patch) | |
tree | 925e1d55720631133584c781ef387d7e577fae5c /libdimension/error.c | |
parent | fc93aba423c69eddbb69a15d8e90f2272759cd62 (diff) | |
download | dimension-69501590eec9c1bc6c7640d17b01ad4d2ce007a5.tar.xz |
Make default fatal error handler nicer.
If we can, only exit the current thread, and print a backtrace.
Diffstat (limited to 'libdimension/error.c')
-rw-r--r-- | libdimension/error.c | 29 |
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 } |