diff options
author | TheCharlatan <seb.kung@gmail.com> | 2023-06-01 16:53:33 -0400 |
---|---|---|
committer | TheCharlatan <seb.kung@gmail.com> | 2023-06-28 09:49:28 +0200 |
commit | e2d680a32d757de0ef8eb836047a0daa1d82e3c4 (patch) | |
tree | 5115b92fc4fe97697c27ad43617984551ae5646c /src/shutdown.cpp | |
parent | d9c7c2fd3ec7b0fcae7e0c9423bff6c6799dd67c (diff) |
util: Add SignalInterrupt class and use in shutdown.cpp
This change helps generalize shutdown code so an interrupt can be
provided to libbitcoinkernel callers. This may also be useful to
eventually de-globalize all of the shutdown code.
Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
Co-authored-by: TheCharlatan <seb.kung@gmail.com>
Diffstat (limited to 'src/shutdown.cpp')
-rw-r--r-- | src/shutdown.cpp | 69 |
1 files changed, 14 insertions, 55 deletions
diff --git a/src/shutdown.cpp b/src/shutdown.cpp index d70017d734..185cad5baf 100644 --- a/src/shutdown.cpp +++ b/src/shutdown.cpp @@ -9,17 +9,15 @@ #include <config/bitcoin-config.h> #endif +#include <kernel/context.h> #include <logging.h> #include <node/interface_ui.h> #include <util/check.h> -#include <util/tokenpipe.h> +#include <util/signalinterrupt.h> #include <warnings.h> -#include <assert.h> #include <atomic> -#ifdef WIN32 -#include <condition_variable> -#endif +#include <cassert> static std::atomic<int>* g_exit_status{nullptr}; @@ -36,76 +34,37 @@ bool AbortNode(const std::string& strMessage, bilingual_str user_message) return false; } -static std::atomic<bool> fRequestShutdown(false); -#ifdef WIN32 -/** On windows it is possible to simply use a condition variable. */ -std::mutex g_shutdown_mutex; -std::condition_variable g_shutdown_cv; -#else -/** On UNIX-like operating systems use the self-pipe trick. - */ -static TokenPipeEnd g_shutdown_r; -static TokenPipeEnd g_shutdown_w; -#endif - -bool InitShutdownState(std::atomic<int>& exit_status) +void InitShutdownState(std::atomic<int>& exit_status) { g_exit_status = &exit_status; -#ifndef WIN32 - std::optional<TokenPipe> pipe = TokenPipe::Make(); - if (!pipe) return false; - g_shutdown_r = pipe->TakeReadEnd(); - g_shutdown_w = pipe->TakeWriteEnd(); -#endif - return true; } void StartShutdown() { -#ifdef WIN32 - std::unique_lock<std::mutex> lk(g_shutdown_mutex); - fRequestShutdown = true; - g_shutdown_cv.notify_one(); -#else - // This must be reentrant and safe for calling in a signal handler, so using a condition variable is not safe. - // Make sure that the token is only written once even if multiple threads call this concurrently or in - // case of a reentrant signal. - if (!fRequestShutdown.exchange(true)) { - // Write an arbitrary byte to the write end of the shutdown pipe. - int res = g_shutdown_w.TokenWrite('x'); - if (res != 0) { - LogPrintf("Sending shutdown token failed\n"); - assert(0); - } + try { + Assert(kernel::g_context)->interrupt(); + } catch (const std::system_error&) { + LogPrintf("Sending shutdown token failed\n"); + assert(0); } -#endif } void AbortShutdown() { - if (fRequestShutdown) { - // Cancel existing shutdown by waiting for it, this will reset condition flags and remove - // the shutdown token from the pipe. - WaitForShutdown(); - } - fRequestShutdown = false; + Assert(kernel::g_context)->interrupt.reset(); } bool ShutdownRequested() { - return fRequestShutdown; + return bool{Assert(kernel::g_context)->interrupt}; } void WaitForShutdown() { -#ifdef WIN32 - std::unique_lock<std::mutex> lk(g_shutdown_mutex); - g_shutdown_cv.wait(lk, [] { return fRequestShutdown.load(); }); -#else - int res = g_shutdown_r.TokenRead(); - if (res != 'x') { + try { + Assert(kernel::g_context)->interrupt.wait(); + } catch (const std::system_error&) { LogPrintf("Reading shutdown token failed\n"); assert(0); } -#endif } |