Bitcoin Core  24.99.0
P2P Digital Currency
shutdown.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <shutdown.h>
7 
8 #if defined(HAVE_CONFIG_H)
10 #endif
11 
12 #include <logging.h>
13 #include <node/interface_ui.h>
14 #include <util/tokenpipe.h>
15 #include <warnings.h>
16 
17 #include <assert.h>
18 #include <atomic>
19 #ifdef WIN32
20 #include <condition_variable>
21 #endif
22 
23 bool AbortNode(const std::string& strMessage, bilingual_str user_message)
24 {
25  SetMiscWarning(Untranslated(strMessage));
26  LogPrintf("*** %s\n", strMessage);
27  if (user_message.empty()) {
28  user_message = _("A fatal internal error occurred, see debug.log for details");
29  }
30  AbortError(user_message);
31  StartShutdown();
32  return false;
33 }
34 
35 static std::atomic<bool> fRequestShutdown(false);
36 #ifdef WIN32
38 std::mutex g_shutdown_mutex;
39 std::condition_variable g_shutdown_cv;
40 #else
45 #endif
46 
48 {
49 #ifndef WIN32
50  std::optional<TokenPipe> pipe = TokenPipe::Make();
51  if (!pipe) return false;
52  g_shutdown_r = pipe->TakeReadEnd();
53  g_shutdown_w = pipe->TakeWriteEnd();
54 #endif
55  return true;
56 }
57 
59 {
60 #ifdef WIN32
61  std::unique_lock<std::mutex> lk(g_shutdown_mutex);
62  fRequestShutdown = true;
63  g_shutdown_cv.notify_one();
64 #else
65  // This must be reentrant and safe for calling in a signal handler, so using a condition variable is not safe.
66  // Make sure that the token is only written once even if multiple threads call this concurrently or in
67  // case of a reentrant signal.
68  if (!fRequestShutdown.exchange(true)) {
69  // Write an arbitrary byte to the write end of the shutdown pipe.
70  int res = g_shutdown_w.TokenWrite('x');
71  if (res != 0) {
72  LogPrintf("Sending shutdown token failed\n");
73  assert(0);
74  }
75  }
76 #endif
77 }
78 
80 {
81  if (fRequestShutdown) {
82  // Cancel existing shutdown by waiting for it, this will reset condition flags and remove
83  // the shutdown token from the pipe.
85  }
86  fRequestShutdown = false;
87 }
88 
90 {
91  return fRequestShutdown;
92 }
93 
95 {
96 #ifdef WIN32
97  std::unique_lock<std::mutex> lk(g_shutdown_mutex);
98  g_shutdown_cv.wait(lk, [] { return fRequestShutdown.load(); });
99 #else
100  int res = g_shutdown_r.TokenRead();
101  if (res != 'x') {
102  LogPrintf("Reading shutdown token failed\n");
103  assert(0);
104  }
105 #endif
106 }
One end of a token pipe.
Definition: tokenpipe.h:15
int TokenWrite(uint8_t token)
Write token to endpoint.
Definition: tokenpipe.cpp:40
int TokenRead()
Read token from endpoint.
Definition: tokenpipe.cpp:58
static std::optional< TokenPipe > Make()
Create a new pipe.
Definition: tokenpipe.cpp:84
constexpr auto AbortError
Definition: interface_ui.h:119
#define LogPrintf(...)
Definition: logging.h:236
void WaitForShutdown()
Wait for StartShutdown to be called in any thread.
Definition: shutdown.cpp:94
static std::atomic< bool > fRequestShutdown(false)
static TokenPipeEnd g_shutdown_w
Definition: shutdown.cpp:44
bool AbortNode(const std::string &strMessage, bilingual_str user_message)
Abort with a message.
Definition: shutdown.cpp:23
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
Definition: shutdown.cpp:89
static TokenPipeEnd g_shutdown_r
On UNIX-like operating systems use the self-pipe trick.
Definition: shutdown.cpp:43
bool InitShutdownState()
Initialize shutdown state.
Definition: shutdown.cpp:47
void StartShutdown()
Request shutdown of the application.
Definition: shutdown.cpp:58
void AbortShutdown()
Clear shutdown flag.
Definition: shutdown.cpp:79
Bilingual messages:
Definition: translation.h:18
bool empty() const
Definition: translation.h:29
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:65
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:48
assert(!tx.IsCoinBase())
void SetMiscWarning(const bilingual_str &warning)
Definition: warnings.cpp:19