Line data Source code
1 : // Copyright (c) 2020-2025 The Dash 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/wpipe.h> 6 : 7 : #include <logging.h> 8 : #include <util/edge.h> 9 : #include <util/sock.h> 10 : 11 : static constexpr int EXPECTED_PIPE_WRITTEN_BYTES = 1; 12 : 13 5642 : WakeupPipe::WakeupPipe(EdgeTriggeredEvents* edge_trig_events) 14 : : m_edge_trig_events{edge_trig_events} 15 2821 : { 16 : #ifdef USE_WAKEUP_PIPE 17 : if (pipe(m_pipe.data()) != 0) { 18 : LogPrintf("Unable to initialize WakeupPipe, pipe() for m_pipe failed with error %s\n", 19 : NetworkErrorString(WSAGetLastError())); 20 : return; 21 : } 22 : for (size_t idx = 0; idx < m_pipe.size(); idx++) { 23 : int flags = fcntl(m_pipe[idx], F_GETFL, 0); 24 : if (fcntl(m_pipe[idx], F_SETFL, flags | O_NONBLOCK) == SOCKET_ERROR) { 25 : LogPrintf("Unable to initialize WakeupPipe, fcntl for O_NONBLOCK on m_pipe[%d] failed with error %s\n", idx, 26 : NetworkErrorString(WSAGetLastError())); 27 : Close(); 28 : return; 29 : } 30 : } 31 : if (edge_trig_events && !edge_trig_events->RegisterPipe(m_pipe[0])) { 32 : LogPrintf("Unable to initialize WakeupPipe, EdgeTriggeredEvents::RegisterPipe() failed for m_pipe[0] = %d\n", 33 : m_pipe[0]); 34 : Close(); 35 : return; 36 : } 37 : m_valid = true; 38 : #else 39 : LogPrintf("Attempting to initialize WakeupPipe without support compiled in!\n"); 40 : #endif /* USE_WAKEUP_PIPE */ 41 2821 : } 42 : 43 5642 : WakeupPipe::~WakeupPipe() 44 2821 : { 45 2821 : if (m_valid) { 46 : #ifdef USE_WAKEUP_PIPE 47 2821 : Drain(); 48 2821 : if (m_edge_trig_events && !m_edge_trig_events->UnregisterPipe(m_pipe[0])) { 49 0 : LogPrintf("Destroying WakeupPipe instance, EdgeTriggeredEvents::UnregisterPipe() failed for m_pipe[0] = %d\n", 50 : m_pipe[0]); 51 0 : } 52 2821 : Close(); 53 : #else 54 : assert(false); 55 : #endif /* USE_WAKEUP_PIPE */ 56 2821 : } 57 5642 : } 58 : 59 2821 : void WakeupPipe::Close() 60 : { 61 : #ifdef USE_WAKEUP_PIPE 62 8463 : for (size_t idx{0}; idx < m_pipe.size(); idx++) { 63 5642 : if (m_pipe[idx] != -1 && close(m_pipe[idx]) != 0) { 64 0 : LogPrintf("close() failed for m_pipe[%d] = %d with error %s\n", idx, m_pipe[idx], 65 : NetworkErrorString(WSAGetLastError())); 66 0 : } 67 5642 : m_pipe[idx] = -1; 68 5642 : } 69 : #else 70 : assert(false); 71 : #endif /* USE_WAKEUP_PIPE */ 72 2821 : } 73 : 74 523251 : void WakeupPipe::Drain() const 75 : { 76 : #ifdef USE_WAKEUP_PIPE 77 523251 : assert(m_valid && m_pipe[0] != -1); 78 : 79 523251 : int ret{0}; 80 523251 : std::array<uint8_t, 128> buf{}; 81 523251 : do { 82 1043739 : ret = read(m_pipe[0], buf.data(), buf.size()); 83 1043739 : } while (ret > 0); 84 : #else 85 : assert(false); 86 : #endif /* USE_WAKEUP_PIPE */ 87 523251 : } 88 : 89 521643 : void WakeupPipe::Write() 90 : { 91 : #ifdef USE_WAKEUP_PIPE 92 521643 : assert(m_valid && m_pipe[1] != -1); 93 : 94 521643 : std::array<uint8_t, EXPECTED_PIPE_WRITTEN_BYTES> buf{}; 95 521643 : int ret = write(m_pipe[1], buf.data(), buf.size()); 96 521643 : if (ret == SOCKET_ERROR) { 97 0 : LogPrintf("write() to m_pipe[1] = %d failed with error %s\n", m_pipe[1], NetworkErrorString(WSAGetLastError())); 98 0 : } 99 521643 : if (ret != EXPECTED_PIPE_WRITTEN_BYTES) { 100 0 : LogPrintf("write() to m_pipe[1] = %d succeeded with unexpected result %d (expected %d)\n", m_pipe[1], ret, 101 : EXPECTED_PIPE_WRITTEN_BYTES); 102 0 : } 103 : 104 521643 : m_need_wakeup = false; 105 : #else 106 : assert(false); 107 : #endif /* USE_WAKEUP_PIPE */ 108 521643 : }