From 712409218e0fb9ff16a2fde198418034b7d77fb6 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Fri, 22 Mar 2019 18:50:57 -0700 Subject: [PATCH] ircd::ctx: Manipulate uncaught exception count on context switch. --- configure.ac | 1 + include/ircd/ctx/continuation.h | 1 + ircd/ctx.cc | 42 ++++++++++++++++++++++++++++++--- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 8044d3002..990f7c365 100644 --- a/configure.ac +++ b/configure.ac @@ -718,6 +718,7 @@ RB_CHK_SYSHEADER(new, [NEW]) RB_CHK_SYSHEADER(regex, [REGEX]) RB_CHK_SYSHEADER(memory_resource, [MEMORY_RESOURCE]) RB_CHK_SYSHEADER(filesystem, [FILESYSTEM]) +RB_CHK_SYSHEADER(cxxabi.h, [CXXABI_H]) dnl unix platform RB_CHK_SYSHEADER(unistd.h, [UNISTD_H]) diff --git a/include/ircd/ctx/continuation.h b/include/ircd/ctx/continuation.h index 78f0ceb25..25d2fe39a 100644 --- a/include/ircd/ctx/continuation.h +++ b/include/ircd/ctx/continuation.h @@ -57,6 +57,7 @@ struct ircd::ctx::continuation ctx *const self; const predicate *const pred; const interruptor *const intr; + const uint uncaught_exceptions; operator const boost::asio::yield_context &() const noexcept; operator boost::asio::yield_context &() noexcept; diff --git a/ircd/ctx.cc b/ircd/ctx.cc index 73dc6756b..5b78f4453 100644 --- a/ircd/ctx.cc +++ b/ircd/ctx.cc @@ -762,11 +762,16 @@ noexcept ircd::ctx::this_ctx::exception_handler::exception_handler() noexcept -:std::exception_ptr{std::current_exception()} +:std::exception_ptr +{ + std::current_exception() +} { assert(bool(*this)); - //assert(!std::uncaught_exceptions()); + + #ifdef HAVE_CXXABI_H __cxa_end_catch(); + #endif // 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 @@ -949,6 +954,14 @@ ircd::ctx::continuation::noop_interruptor{[] return; }}; +#ifdef HAVE_CXXABI_H +struct __cxxabiv1::__cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +}; +#endif + // // continuation // @@ -969,6 +982,10 @@ try { &intr } +,uncaught_exceptions +{ + uint(std::uncaught_exceptions()) +} { assert(self != nullptr); assert(self->notes <= 1); @@ -986,7 +1003,6 @@ try // cannot interleave _cxa_begin_catch() and __cxa_end_catch() by yielding // the ircd::ctx in an exception handler. assert(!std::current_exception()); - //assert(!std::uncaught_exceptions()); // Point to this continuation instance (which is on the context's stack) // from the context's instance. This allows its features to be accessed @@ -1000,6 +1016,15 @@ try // its execution run and is now yielding. mark(prof::event::YIELD); + #ifdef HAVE_CXXABI_H + using __cxxabiv1::__cxa_get_globals_fast; + assert(__cxa_get_globals_fast()); + assert(__cxa_get_globals_fast()->uncaughtExceptions == uncaught_exceptions); + __cxa_get_globals_fast()->uncaughtExceptions = 0; + #else + assert(!uncaught_exceptions); + #endif + // Null the fundamental current context register as the last operation // during execution before yielding. When a context resumes it will // restore this register; otherwise it remains null for executions on @@ -1024,6 +1049,17 @@ noexcept // upon resuming execution. ircd::ctx::current = self; + #ifdef HAVE_CXXABI_H + using __cxxabiv1::__cxa_get_globals_fast; + assert(__cxa_get_globals_fast()); + assert(__cxa_get_globals_fast()->uncaughtExceptions == 0); + __cxa_get_globals_fast()->uncaughtExceptions = uncaught_exceptions; + assert(uint(std::uncaught_exceptions()) == uncaught_exceptions); + #else + assert(std::uncaught_exceptions() == 0); + assert(uncaught_exceptions == 0); + #endif + // Tell the profiler this is the point where the context is now resuming. // On some optimized builds this might lead nowhere. mark(prof::event::CONTINUE);