summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-09-30 12:29:08 -0400
committerTavian Barnes <tavianator@gmail.com>2010-09-30 17:19:39 -0400
commit32ccbb213b2a2d419581690d42611c375c3d22cf (patch)
tree1cdfd44c2936b0aa3d96ca54fbe30dab3d0a4c0e
parent312387496ec8f30b50dcb21f47e74e4eb135c63b (diff)
downloaddimension-32ccbb213b2a2d419581690d42611c375c3d22cf.tar.xz
Fix behaviour when the error handler itself calls dmnsn_error().
-rw-r--r--libdimension/error.c10
-rw-r--r--libdimension/threads.c10
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;
}