Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/util/signalinterrupt.cpp
Line
Count
Source
1
// Copyright (c) 2022 The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <util/signalinterrupt.h>
6
7
#ifdef WIN32
8
#include <mutex>
9
#else
10
#include <util/tokenpipe.h>
11
#endif
12
13
#include <ios>
14
#include <optional>
15
16
namespace util {
17
18
11.0k
SignalInterrupt::SignalInterrupt() : m_flag{false}
19
11.0k
{
20
11.0k
#ifndef WIN32
21
11.0k
    std::optional<TokenPipe> pipe = TokenPipe::Make();
22
11.0k
    if (!pipe) throw std::ios_base::failure("Could not create TokenPipe");
  Branch (22:9): [True: 0, False: 11.0k]
23
11.0k
    m_pipe_r = pipe->TakeReadEnd();
24
11.0k
    m_pipe_w = pipe->TakeWriteEnd();
25
11.0k
#endif
26
11.0k
}
27
28
SignalInterrupt::operator bool() const
29
4.66M
{
30
4.66M
    return m_flag;
31
4.66M
}
32
33
bool SignalInterrupt::reset()
34
0
{
35
    // Cancel existing interrupt by waiting for it, this will reset condition flags and remove
36
    // the token from the pipe.
37
0
    if (*this && !wait()) return false;
  Branch (37:9): [True: 0, False: 0]
  Branch (37:18): [True: 0, False: 0]
38
0
    m_flag = false;
39
0
    return true;
40
0
}
41
42
bool SignalInterrupt::operator()()
43
11.0k
{
44
#ifdef WIN32
45
    std::unique_lock<std::mutex> lk(m_mutex);
46
    m_flag = true;
47
    m_cv.notify_one();
48
#else
49
    // This must be reentrant and safe for calling in a signal handler, so using a condition variable is not safe.
50
    // Make sure that the token is only written once even if multiple threads call this concurrently or in
51
    // case of a reentrant signal.
52
11.0k
    if (!m_flag.exchange(true)) {
  Branch (52:9): [True: 11.0k, False: 0]
53
        // Write an arbitrary byte to the write end of the pipe.
54
11.0k
        int res = m_pipe_w.TokenWrite('x');
55
11.0k
        if (res != 0) {
  Branch (55:13): [True: 0, False: 11.0k]
56
0
            return false;
57
0
        }
58
11.0k
    }
59
11.0k
#endif
60
11.0k
    return true;
61
11.0k
}
62
63
bool SignalInterrupt::wait()
64
11.0k
{
65
#ifdef WIN32
66
    std::unique_lock<std::mutex> lk(m_mutex);
67
    m_cv.wait(lk, [this] { return m_flag.load(); });
68
#else
69
11.0k
    int res = m_pipe_r.TokenRead();
70
11.0k
    if (res != 'x') {
  Branch (70:9): [True: 0, False: 11.0k]
71
0
        return false;
72
0
    }
73
11.0k
#endif
74
11.0k
    return true;
75
11.0k
}
76
77
} // namespace util