summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoranonymous <local@localhost>2011-01-10 13:20:01 +0000
committeranonymous <local@localhost>2011-01-10 13:20:01 +0000
commitc286ec85fb64e6a0e01bc4c6ed3fd9ef5ddee8f7 (patch)
tree99334ae8da05db054006a652a457556dd89c7a3f
parentd473efff11e07e5761b3a873e3d00664e21159e2 (diff)
downloadlibcxxrt-c286ec85fb64e6a0e01bc4c6ed3fd9ef5ddee8f7.tar.gz
libcxxrt-c286ec85fb64e6a0e01bc4c6ed3fd9ef5ddee8f7.tar.bz2
libcxxrt-c286ec85fb64e6a0e01bc4c6ed3fd9ef5ddee8f7.tar.xz
Make std::set_unexpected and std::set_terminate set global (process)
unexpected and terminate handlers, respectively. Added pathscale:: versions of both (not exposed in the headers, so not - yet - part of the public API), which retain the old behaviour and set a thread-local version. Also added pathscale::set_use_thread_local_handlers(), which allows the user to request the thread-local behaviour from the std:: versions. Also not exposed via a header yet. The pathscale:: namespace might not be the most sensible place for these, and some thought should be given to this before actually making them public.
-rw-r--r--src/exception.cc35
1 files changed, 31 insertions, 4 deletions
diff --git a/src/exception.cc b/src/exception.cc
index 9c4bc4d..43229c2 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -136,6 +136,11 @@ struct __cxa_thread_info
__cxa_eh_globals globals;
};
+/** The global termination handler. */
+static terminate_handler terminateHandler = abort;
+/** The global unexpected exception handler. */
+static unexpected_handler unexpectedHandler = abort;
+
/** Key used for thread-local data. */
static pthread_key_t eh_key;
@@ -488,7 +493,7 @@ extern "C" void __cxa_throw(void *thrown_exception,
info->globals.uncaughtExceptions++;
_Unwind_Reason_Code err = _Unwind_RaiseException(&ex->unwindHeader);
- std::terminate();
+ report_failure(err, thrown_exception);
}
/**
@@ -963,8 +968,14 @@ extern "C" void *__cxa_get_exception_ptr(void *exceptionObject)
}
-namespace std
+static bool thread_local_handlers = false;
+
+namespace pathscale
{
+ void set_use_thread_local_handlers(bool flag)
+ {
+ thread_local_handlers = flag;
+ }
unexpected_handler set_unexpected(unexpected_handler f) throw()
{
static __cxa_thread_info *info = thread_info();
@@ -979,6 +990,21 @@ namespace std
info->terminateHandler = f;
return old;
}
+}
+
+namespace std
+{
+ unexpected_handler set_unexpected(unexpected_handler f) throw()
+ {
+ if (thread_local_handlers) { return pathscale::set_unexpected(f); }
+
+ return __sync_lock_test_and_set(&unexpectedHandler, f);
+ }
+ terminate_handler set_terminate(terminate_handler f) throw()
+ {
+ if (thread_local_handlers) { return pathscale::set_terminate(f); }
+ return __sync_lock_test_and_set(&terminateHandler, f);
+ }
void terminate()
{
static __cxa_thread_info *info = thread_info_fast();
@@ -987,8 +1013,9 @@ namespace std
info->terminateHandler();
// Should not be reached - a terminate handler is not expected to
// return.
+ abort();
}
- abort();
+ terminateHandler();
}
void unexpected()
{
@@ -1000,7 +1027,7 @@ namespace std
// return.
abort();
}
- terminate();
+ unexpectedHandler();
}
bool uncaught_exception() throw() {
__cxa_thread_info *info = thread_info();