mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 16:22:35 +01:00
ircd::ctx: Device to allow context switching in exception handler.
This commit is contained in:
parent
ecce9d0433
commit
441a692dfc
2 changed files with 40 additions and 0 deletions
|
@ -63,6 +63,7 @@ namespace ircd::ctx { inline namespace this_ctx
|
|||
/// Interface to the currently running context
|
||||
{
|
||||
struct critical_assertion; // Assert no yielding for a section
|
||||
struct exception_handler; // Must be present to yield in a handler
|
||||
|
||||
/// Points to the currently running context or null for main stack (do not modify)
|
||||
extern __thread struct ctx *current;
|
||||
|
@ -147,6 +148,27 @@ class ircd::ctx::this_ctx::critical_assertion
|
|||
~critical_assertion() noexcept;
|
||||
};
|
||||
|
||||
/// An instance of exception_handler must be present to allow a context
|
||||
/// switch inside a catch block. This is due to ABI limitations that stack
|
||||
/// exceptions with thread-local assumptions and don't expect catch blocks
|
||||
/// on the same thread to interleave when we switch the stack.
|
||||
///
|
||||
/// We first increment the refcount for the caught exception so it remains
|
||||
/// intuitively accessible for the rest of the catch block. Then the presence
|
||||
/// of this object makes the ABI believe the catch block has ended.
|
||||
///
|
||||
/// The exception cannot then be rethrown. DO NOT RETHROW THE EXCEPTION.
|
||||
///
|
||||
struct ircd::ctx::this_ctx::exception_handler
|
||||
:std::exception_ptr
|
||||
{
|
||||
exception_handler() noexcept;
|
||||
exception_handler(exception_handler &&) = delete;
|
||||
exception_handler(const exception_handler &) = delete;
|
||||
exception_handler &operator=(exception_handler &&) = delete;
|
||||
exception_handler &operator=(const exception_handler &) = delete;
|
||||
};
|
||||
|
||||
/// This overload matches ::sleep() and acts as a drop-in for ircd contexts.
|
||||
/// interruption point.
|
||||
inline void
|
||||
|
|
18
ircd/ctx.cc
18
ircd/ctx.cc
|
@ -9,6 +9,7 @@
|
|||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#include <RB_INC_X86INTRIN_H
|
||||
#include <cxxabi.h>
|
||||
#include <ircd/asio.h>
|
||||
|
||||
/// Internal context implementation
|
||||
|
@ -480,6 +481,20 @@ ircd::ctx::id(const ctx &ctx)
|
|||
return ctx.id;
|
||||
}
|
||||
|
||||
//
|
||||
// exception_handler
|
||||
//
|
||||
|
||||
ircd::ctx::this_ctx::exception_handler::exception_handler()
|
||||
noexcept
|
||||
:std::exception_ptr{std::current_exception()}
|
||||
{
|
||||
assert(bool(*this));
|
||||
assert(!std::uncaught_exceptions());
|
||||
__cxa_end_catch();
|
||||
assert(!std::current_exception());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ctx/continuation.h
|
||||
|
@ -519,6 +534,9 @@ ircd::ctx::continuation::continuation(ctx *const &self)
|
|||
assert(self != nullptr);
|
||||
assert(self->notes <= 1);
|
||||
|
||||
// Note: Construct an instance of ctx::exception_handler to enable yielding
|
||||
// in your catch block.
|
||||
//
|
||||
// GNU cxxabi uses a singly-linked forward list (aka the 'exception
|
||||
// stack') for pending exception activities. Due to this limitation we
|
||||
// cannot interleave _cxa_begin_catch() and __cxa_end_catch() by yielding
|
||||
|
|
Loading…
Reference in a new issue