diff options
author | anonymous <local@localhost> | 2011-01-10 13:20:01 +0000 |
---|---|---|
committer | anonymous <local@localhost> | 2011-01-10 13:20:01 +0000 |
commit | c286ec85fb64e6a0e01bc4c6ed3fd9ef5ddee8f7 (patch) | |
tree | 99334ae8da05db054006a652a457556dd89c7a3f | |
parent | d473efff11e07e5761b3a873e3d00664e21159e2 (diff) | |
download | libcxxrt-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.cc | 35 |
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(); |