LCOV - code coverage report
Current view: top level - src - shutdown.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 4 47 8.5 %
Date: 2026-06-25 07:23:51 Functions: 3 10 30.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 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)
       9             : #include <config/bitcoin-config.h>
      10             : #endif
      11             : 
      12             : #include <logging.h>
      13             : #include <util/tokenpipe.h>
      14             : 
      15             : #include <node/interface_ui.h>
      16             : #include <warnings.h>
      17             : 
      18             : #include <assert.h>
      19             : #include <atomic>
      20             : #ifdef WIN32
      21             : #include <condition_variable>
      22             : #endif
      23             : 
      24           0 : bool AbortNode(const std::string& strMessage, bilingual_str user_message)
      25             : {
      26           0 :     SetMiscWarning(Untranslated(strMessage));
      27           0 :     LogPrintf("*** %s\n", strMessage);
      28           0 :     if (user_message.empty()) {
      29           0 :         user_message = _("A fatal internal error occurred, see debug.log for details");
      30           0 :     }
      31           0 :     AbortError(user_message);
      32           0 :     StartShutdown();
      33           0 :     return false;
      34           0 : }
      35             : 
      36             : static std::atomic<bool> fRequestShutdown(false);
      37             : static std::atomic<bool> fRequestRestart(false);
      38             : 
      39             : #ifdef WIN32
      40             : /** On windows it is possible to simply use a condition variable. */
      41             : std::mutex g_shutdown_mutex;
      42             : std::condition_variable g_shutdown_cv;
      43             : #else
      44             : /** On UNIX-like operating systems use the self-pipe trick.
      45             :  */
      46         146 : static TokenPipeEnd g_shutdown_r;
      47         146 : static TokenPipeEnd g_shutdown_w;
      48             : #endif
      49             : 
      50           0 : bool InitShutdownState()
      51             : {
      52             : #ifndef WIN32
      53           0 :     std::optional<TokenPipe> pipe = TokenPipe::Make();
      54           0 :     if (!pipe) return false;
      55           0 :     g_shutdown_r = pipe->TakeReadEnd();
      56           0 :     g_shutdown_w = pipe->TakeWriteEnd();
      57             : #endif
      58           0 :     return true;
      59           0 : }
      60             : 
      61           0 : void StartShutdown()
      62             : {
      63             : #ifdef WIN32
      64             :     std::unique_lock<std::mutex> lk(g_shutdown_mutex);
      65             :     fRequestShutdown = true;
      66             :     g_shutdown_cv.notify_one();
      67             : #else
      68             :     // This must be reentrant and safe for calling in a signal handler, so using a condition variable is not safe.
      69             :     // Make sure that the token is only written once even if multiple threads call this concurrently or in
      70             :     // case of a reentrant signal.
      71           0 :     if (!fRequestShutdown.exchange(true)) {
      72             :         // Write an arbitrary byte to the write end of the shutdown pipe.
      73           0 :         int res = g_shutdown_w.TokenWrite('x');
      74           0 :         if (res != 0) {
      75           0 :             LogPrintf("Sending shutdown token failed\n");
      76           0 :             assert(0);
      77             :         }
      78           0 :     }
      79             : #endif
      80           0 : }
      81           0 : void StartRestart()
      82             : {
      83           0 :     fRequestRestart = true;
      84           0 :     StartShutdown();
      85           0 : }
      86             : 
      87           0 : void AbortShutdown()
      88             : {
      89           0 :     if (fRequestShutdown) {
      90             :         // Cancel existing shutdown by waiting for it, this will reset condition flags and remove
      91             :         // the shutdown token from the pipe.
      92           0 :         WaitForShutdown();
      93           0 :     }
      94           0 :     fRequestShutdown = false;
      95           0 : }
      96             : 
      97       25790 : bool ShutdownRequested()
      98             : {
      99       25790 :     return fRequestShutdown;
     100             : }
     101             : 
     102           0 : bool RestartRequested()
     103             : {
     104           0 :     return fRequestRestart;
     105             : }
     106             : 
     107           0 : void WaitForShutdown()
     108             : {
     109             : #ifdef WIN32
     110             :     std::unique_lock<std::mutex> lk(g_shutdown_mutex);
     111             :     g_shutdown_cv.wait(lk, [] { return fRequestShutdown.load(); });
     112             : #else
     113           0 :     int res = g_shutdown_r.TokenRead();
     114           0 :     if (res != 'x') {
     115           0 :         LogPrintf("Reading shutdown token failed\n");
     116           0 :         assert(0);
     117             :     }
     118             : #endif
     119           0 : }

Generated by: LCOV version 1.16