mirror of
https://github.com/matrix-construct/construct
synced 2024-12-29 17:04:03 +01:00
ircd::ctx: Split exception_handler w/ cxxabi header requirement.
This commit is contained in:
parent
480834f49b
commit
471c08a41e
4 changed files with 136 additions and 56 deletions
|
@ -11,11 +11,10 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_CTX_EXCEPTION_HANDLER_H
|
||||
|
||||
namespace ircd::ctx {
|
||||
inline namespace this_ctx
|
||||
namespace ircd::ctx
|
||||
{
|
||||
struct exception_handler;
|
||||
}}
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -28,9 +27,14 @@ inline namespace this_ctx
|
|||
///
|
||||
/// The exception cannot then be rethrown. DO NOT RETHROW THE EXCEPTION.
|
||||
///
|
||||
struct ircd::ctx::this_ctx::exception_handler
|
||||
struct ircd::ctx::exception_handler
|
||||
:std::exception_ptr
|
||||
{
|
||||
static uint uncaught_exceptions(const uint &) noexcept;
|
||||
static uint uncaught_exceptions() noexcept;
|
||||
static void end_catch() noexcept;
|
||||
|
||||
public:
|
||||
exception_handler() noexcept;
|
||||
exception_handler(exception_handler &&) = delete;
|
||||
exception_handler(const exception_handler &) = delete;
|
||||
|
|
|
@ -149,6 +149,7 @@ libircd_la_SOURCES += prof.cc
|
|||
libircd_la_SOURCES += fs.cc
|
||||
libircd_la_SOURCES += ios.cc
|
||||
libircd_la_SOURCES += ctx.cc
|
||||
libircd_la_SOURCES += ctx_eh.cc
|
||||
libircd_la_SOURCES += ctx_ole.cc
|
||||
if AIO
|
||||
libircd_la_SOURCES += fs_aio.cc
|
||||
|
|
59
ircd/ctx.cc
59
ircd/ctx.cc
|
@ -8,7 +8,6 @@
|
|||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <ircd/asio.h>
|
||||
#include "ctx.h"
|
||||
|
||||
|
@ -756,30 +755,6 @@ noexcept
|
|||
interruptible(theirs, std::nothrow);
|
||||
}
|
||||
|
||||
//
|
||||
// exception_handler
|
||||
//
|
||||
|
||||
ircd::ctx::this_ctx::exception_handler::exception_handler()
|
||||
noexcept
|
||||
:std::exception_ptr
|
||||
{
|
||||
std::current_exception()
|
||||
}
|
||||
{
|
||||
assert(bool(*this));
|
||||
|
||||
#ifdef HAVE_CXXABI_H
|
||||
if(current)
|
||||
__cxxabiv1::__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
|
||||
// not on any ctx currently.
|
||||
assert(!current || !std::uncaught_exceptions());
|
||||
}
|
||||
|
||||
//
|
||||
// critical_assertion
|
||||
//
|
||||
|
@ -996,14 +971,6 @@ ircd::ctx::continuation::noop_interruptor{[]
|
|||
return;
|
||||
}};
|
||||
|
||||
#ifdef HAVE_CXXABI_H
|
||||
struct __cxxabiv1::__cxa_eh_globals
|
||||
{
|
||||
__cxa_exception *caughtExceptions;
|
||||
unsigned int uncaughtExceptions;
|
||||
};
|
||||
#endif
|
||||
|
||||
//
|
||||
// continuation
|
||||
//
|
||||
|
@ -1025,7 +992,7 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
|||
}
|
||||
,uncaught_exceptions
|
||||
{
|
||||
uint(std::uncaught_exceptions())
|
||||
exception_handler::uncaught_exceptions(0)
|
||||
}
|
||||
{
|
||||
assert(self != nullptr);
|
||||
|
@ -1036,6 +1003,10 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
|||
assert_critical();
|
||||
assert(!critical_asserted);
|
||||
|
||||
// Confirming the uncaught exception count was saved and set to zero in the
|
||||
// initializer list.
|
||||
assert(!std::uncaught_exceptions());
|
||||
|
||||
// Note: Construct an instance of ctx::exception_handler to enable yielding
|
||||
// in your catch block.
|
||||
//
|
||||
|
@ -1057,15 +1028,6 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
|||
// 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
|
||||
|
||||
// Check that we saved a valid context reference to this object for later.
|
||||
assert(self->yc);
|
||||
|
||||
|
@ -1097,16 +1059,9 @@ 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
|
||||
// Restore the uncaught exception count for this context to the cxxabi
|
||||
assert(std::uncaught_exceptions() == 0);
|
||||
assert(uncaught_exceptions == 0);
|
||||
#endif
|
||||
exception_handler::uncaught_exceptions(uncaught_exceptions);
|
||||
|
||||
// Tell the profiler this is the point where the context is now resuming.
|
||||
// On some optimized builds this might lead nowhere.
|
||||
|
|
120
ircd/ctx_eh.cc
Normal file
120
ircd/ctx_eh.cc
Normal file
|
@ -0,0 +1,120 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// 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 <RB_INC_CXXABI_H
|
||||
#include <ircd/asio.h>
|
||||
#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
|
||||
{
|
||||
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
|
||||
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
|
||||
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
|
Loading…
Reference in a new issue