mirror of
https://github.com/matrix-construct/construct
synced 2024-11-28 17:52:54 +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
|
#pragma once
|
||||||
#define HAVE_IRCD_CTX_EXCEPTION_HANDLER_H
|
#define HAVE_IRCD_CTX_EXCEPTION_HANDLER_H
|
||||||
|
|
||||||
namespace ircd::ctx {
|
namespace ircd::ctx
|
||||||
inline namespace this_ctx
|
|
||||||
{
|
{
|
||||||
struct exception_handler;
|
struct exception_handler;
|
||||||
}}
|
}
|
||||||
|
|
||||||
/// An instance of exception_handler must be present to allow a context
|
/// 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
|
/// 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.
|
/// 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
|
: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() noexcept;
|
||||||
exception_handler(exception_handler &&) = delete;
|
exception_handler(exception_handler &&) = delete;
|
||||||
exception_handler(const 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 += fs.cc
|
||||||
libircd_la_SOURCES += ios.cc
|
libircd_la_SOURCES += ios.cc
|
||||||
libircd_la_SOURCES += ctx.cc
|
libircd_la_SOURCES += ctx.cc
|
||||||
|
libircd_la_SOURCES += ctx_eh.cc
|
||||||
libircd_la_SOURCES += ctx_ole.cc
|
libircd_la_SOURCES += ctx_ole.cc
|
||||||
if AIO
|
if AIO
|
||||||
libircd_la_SOURCES += fs_aio.cc
|
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
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
// full license for this software is available in the LICENSE file.
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
#include <cxxabi.h>
|
|
||||||
#include <ircd/asio.h>
|
#include <ircd/asio.h>
|
||||||
#include "ctx.h"
|
#include "ctx.h"
|
||||||
|
|
||||||
|
@ -756,30 +755,6 @@ noexcept
|
||||||
interruptible(theirs, std::nothrow);
|
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
|
// critical_assertion
|
||||||
//
|
//
|
||||||
|
@ -996,14 +971,6 @@ ircd::ctx::continuation::noop_interruptor{[]
|
||||||
return;
|
return;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
#ifdef HAVE_CXXABI_H
|
|
||||||
struct __cxxabiv1::__cxa_eh_globals
|
|
||||||
{
|
|
||||||
__cxa_exception *caughtExceptions;
|
|
||||||
unsigned int uncaughtExceptions;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// continuation
|
// continuation
|
||||||
//
|
//
|
||||||
|
@ -1025,7 +992,7 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
||||||
}
|
}
|
||||||
,uncaught_exceptions
|
,uncaught_exceptions
|
||||||
{
|
{
|
||||||
uint(std::uncaught_exceptions())
|
exception_handler::uncaught_exceptions(0)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assert(self != nullptr);
|
assert(self != nullptr);
|
||||||
|
@ -1036,6 +1003,10 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
||||||
assert_critical();
|
assert_critical();
|
||||||
assert(!critical_asserted);
|
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
|
// Note: Construct an instance of ctx::exception_handler to enable yielding
|
||||||
// in your catch block.
|
// in your catch block.
|
||||||
//
|
//
|
||||||
|
@ -1057,15 +1028,6 @@ ircd::ctx::continuation::continuation(const predicate &pred,
|
||||||
// its execution run and is now yielding.
|
// its execution run and is now yielding.
|
||||||
mark(prof::event::YIELD);
|
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.
|
// Check that we saved a valid context reference to this object for later.
|
||||||
assert(self->yc);
|
assert(self->yc);
|
||||||
|
|
||||||
|
@ -1097,16 +1059,9 @@ noexcept
|
||||||
// upon resuming execution.
|
// upon resuming execution.
|
||||||
ircd::ctx::current = self;
|
ircd::ctx::current = self;
|
||||||
|
|
||||||
#ifdef HAVE_CXXABI_H
|
// Restore the uncaught exception count for this context to the cxxabi
|
||||||
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(std::uncaught_exceptions() == 0);
|
||||||
assert(uncaught_exceptions == 0);
|
exception_handler::uncaught_exceptions(uncaught_exceptions);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Tell the profiler this is the point where the context is now resuming.
|
// Tell the profiler this is the point where the context is now resuming.
|
||||||
// On some optimized builds this might lead nowhere.
|
// 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