3#include <sysio/vm/exceptions.hpp>
4#include <sysio/vm/utils.hpp>
13namespace sysio {
namespace vm {
17 inline thread_local
std::atomic<sigjmp_buf*> signal_dest = ATOMIC_VAR_INIT(
nullptr);
27 sigjmp_buf* dest = std::atomic_load(&signal_dest);
29 siglongjmp(*dest, sig);
31 struct sigaction* prev_action;
36 default: std::abort();
38 if (!prev_action) std::abort();
39 if (prev_action->sa_flags & SA_SIGINFO) {
42 prev_action->sa_sigaction(sig, info, uap);
44 if(prev_action->sa_handler == SIG_DFL) {
46 sigaction(sig, prev_action,
nullptr);
48 }
else if(prev_action->sa_handler == SIG_IGN) {
51 prev_action->sa_handler(sig);
63 static_assert(std::is_trivially_destructible_v<std::decay_t<F>>,
"longjmp has undefined behavior when it bypasses destructors.");
64 bool caught_exception =
false;
68 saved_exception = std::current_exception();
71 caught_exception =
true;
73 if (caught_exception) {
75 sigemptyset(&block_mask);
76 sigaddset(&block_mask, SIGPROF);
77 pthread_sigmask(SIG_BLOCK, &block_mask,
nullptr);
78 sigjmp_buf* dest = std::atomic_load(&signal_dest);
79 siglongjmp(*dest, -1);
84 [[noreturn]]
inline void throw_(
const char* msg) {
85 saved_exception = std::make_exception_ptr(E{msg});
87 sigemptyset(&block_mask);
88 sigaddset(&block_mask, SIGPROF);
89 pthread_sigmask(SIG_BLOCK, &block_mask,
nullptr);
90 sigjmp_buf* dest = std::atomic_load(&signal_dest);
91 siglongjmp(*dest, -1);
97 sigemptyset(&sa.sa_mask);
98 sigaddset(&sa.sa_mask, SIGPROF);
99 sa.sa_flags = SA_NODEFER | SA_SIGINFO;
108 static_assert(std::atomic<sigjmp_buf*>::is_always_lock_free,
"Atomic pointers must be lock-free to be async signal safe.");
122 template<
typename F,
typename E>
126 sigjmp_buf*
volatile old_signal_handler =
nullptr;
128 if((sig = sigsetjmp(dest, 1)) == 0) {
136 old_signal_handler = std::atomic_exchange(&signal_dest, &dest);
137 sigset_t unblock_mask, old_sigmask;
138 sigemptyset(&unblock_mask);
139 sigaddset(&unblock_mask, SIGSEGV);
140 sigaddset(&unblock_mask, SIGBUS);
141 sigaddset(&unblock_mask, SIGFPE);
142 sigaddset(&unblock_mask, SIGPROF);
143 pthread_sigmask(SIG_UNBLOCK, &unblock_mask, &old_sigmask);
146 pthread_sigmask(SIG_SETMASK, &old_sigmask,
nullptr);
147 std::atomic_store(&signal_dest, old_signal_handler);
149 pthread_sigmask(SIG_SETMASK, &old_sigmask,
nullptr);
150 std::atomic_store(&signal_dest, old_signal_handler);
154 std::atomic_store(&signal_dest, old_signal_handler);
156 std::exception_ptr exception = std::move(saved_exception);
157 saved_exception =
nullptr;
158 std::rethrow_exception(exception);
std::shared_ptr< exception > exception_ptr
__attribute__((always_inline)) inline uint64_t rotl64(uint64_t x
auto invoke_with_signal_handler(F &&f, E &&e)
__attribute__((visibility("default"))) inline thread_local std __attribute__((visibility("default"))) inline thread_local std struct sigaction prev_signal_handler
void setup_signal_handler()
void setup_signal_handler_impl()
void ignore_unused_variable_warning(T &...)
void longjmp_on_exception(F &&f)
void throw_(const char *msg)
void signal_handler(int sig, siginfo_t *info, void *uap)