diff options
author | Tavian Barnes <tavianator@gmail.com> | 2010-09-30 12:29:08 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2010-09-30 17:19:39 -0400 |
commit | 32ccbb213b2a2d419581690d42611c375c3d22cf (patch) | |
tree | 1cdfd44c2936b0aa3d96ca54fbe30dab3d0a4c0e /libdimension | |
parent | 312387496ec8f30b50dcb21f47e74e4eb135c63b (diff) | |
download | dimension-32ccbb213b2a2d419581690d42611c375c3d22cf.tar.xz |
Fix behaviour when the error handler itself calls dmnsn_error().
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/error.c | 10 | ||||
-rw-r--r-- | libdimension/threads.c | 10 |
2 files changed, 16 insertions, 4 deletions
diff --git a/libdimension/error.c b/libdimension/error.c index 11b4805..721b45c 100644 --- a/libdimension/error.c +++ b/libdimension/error.c @@ -133,14 +133,22 @@ void dmnsn_set_fatal_error_fn(dmnsn_fatal_error_fn *fatal) } } +/* Prevent infinite recursion if the fatal error function itself calls + dmnsn_error() */ +static __thread bool dmnsn_tl_exiting = false; + static void dmnsn_default_fatal_error_fn() { dmnsn_backtrace(stderr); - if (dmnsn_is_main_thread()) { + if (dmnsn_tl_exiting) { + abort(); + } else if (dmnsn_is_main_thread()) { exit(EXIT_FAILURE); } else { + dmnsn_tl_exiting = true; + int *ret = malloc(sizeof(int)); /* Don't use dmnsn_malloc */ if (ret) *ret = 1; diff --git a/libdimension/threads.c b/libdimension/threads.c index 1f1acd5..2c00cc8 100644 --- a/libdimension/threads.c +++ b/libdimension/threads.c @@ -19,6 +19,7 @@ *************************************************************************/ #include "dimension-impl.h" +#include <pthread.h> typedef struct dmnsn_thread_payload { dmnsn_thread_fn *thread_fn; @@ -29,7 +30,10 @@ typedef struct dmnsn_thread_payload { static void dmnsn_thread_cleanup(void *arg) { - dmnsn_progress *progress = arg; + dmnsn_thread_payload *payload = arg; + dmnsn_progress *progress = payload->progress; + dmnsn_free(payload); + dmnsn_done_progress(progress); } @@ -38,11 +42,11 @@ dmnsn_thread(void *arg) { dmnsn_thread_payload *payload = arg; int *ret; - pthread_cleanup_push(&dmnsn_thread_cleanup, payload->progress); + + pthread_cleanup_push(&dmnsn_thread_cleanup, payload); ret = dmnsn_malloc(sizeof(int)); *ret = (*payload->thread_fn)(payload->arg); pthread_cleanup_pop(1); - dmnsn_free(payload); return ret; } |