// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2019 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #include #include "ctx.h" #ifdef HAVE_CXXABI_H struct __cxxabiv1::__cxa_eh_globals { __cxa_exception *caughtExceptions; unsigned int uncaughtExceptions; }; #endif // // exception_handler // ircd::ctx::exception_handler::exception_handler() noexcept :std::exception_ptr { // capture a shared reference of the current exception before the catch // block closes around it. std::current_exception() } { assert(bool(*this)); // close the catch block. end_catch(); // We don't yet support more levels of exceptions; after ending this // catch we can't still be in another one. This doesn't apply if we're // not on any ctx currently. assert(!current || !std::uncaught_exceptions()); } // // util // #ifdef HAVE_CXXABI_H void ircd::ctx::exception_handler::end_catch() noexcept { // Only close the catch block if we're actually on an ircd::ctx. This // allows the same codepath with a ctx::exception_handler to be used // outside of the ircd::ctx system to not incur any unexpected or // potential issues with ending the catch manually. if(likely(current)) __cxxabiv1::__cxa_end_catch(); } #else #warning "CXXABI not available. Context switch inside catch block may be unsafe!" void ircd::ctx::exception_handler::end_catch() noexcept { } #endif #ifdef HAVE_CXXABI_H /// Get the uncaught exception count uint ircd::ctx::exception_handler::uncaught_exceptions() noexcept { const auto &cxa_globals { __cxxabiv1::__cxa_get_globals_fast() }; assert(cxa_globals); return cxa_globals->uncaughtExceptions; } #else #warning "CXXABI not available. Context switch with uncaught exceptions may be unsafe!" uint ircd::ctx::exception_handler::uncaught_exceptions() noexcept { return std::uncaught_exceptions(); } #endif #ifdef HAVE_CXXABI_H /// Set the uncaught exception count and return the previous value. uint ircd::ctx::exception_handler::uncaught_exceptions(const uint &val) noexcept { const auto &cxa_globals { __cxxabiv1::__cxa_get_globals_fast() }; assert(cxa_globals); const auto ret { cxa_globals->uncaughtExceptions }; assert(unsigned(ret) == unsigned(std::uncaught_exceptions())); cxa_globals->uncaughtExceptions = val; return ret; } #else #warning "CXXABI not available. Context switch with uncaught exceptions may be unsafe!" uint ircd::ctx::exception_handler::uncaught_exceptions(const uint &val) noexcept { assert(std::uncaught_exceptions() == val); return std::uncaught_exceptions(); } #endif