Branch data Line data Source code
1 : : // Copyright (c) 2021-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 : : #include <util/tokenpipe.h> 5 : : 6 : : #if defined(HAVE_CONFIG_H) 7 : : #include <config/bitcoin-config.h> 8 : : #endif 9 : : 10 : : #ifndef WIN32 11 : : 12 : : #include <errno.h> 13 : : #include <fcntl.h> 14 : : #include <optional> 15 : : #include <unistd.h> 16 : : 17 : 0 : TokenPipeEnd TokenPipe::TakeReadEnd() 18 : : { 19 : 0 : TokenPipeEnd res(m_fds[0]); 20 : 0 : m_fds[0] = -1; 21 : 0 : return res; 22 [ # # ]: 0 : } 23 : : 24 : 0 : TokenPipeEnd TokenPipe::TakeWriteEnd() 25 : : { 26 : 0 : TokenPipeEnd res(m_fds[1]); 27 : 0 : m_fds[1] = -1; 28 : 0 : return res; 29 [ # # ]: 0 : } 30 : : 31 : 0 : TokenPipeEnd::TokenPipeEnd(int fd) : m_fd(fd) 32 : : { 33 : 0 : } 34 : : 35 : 0 : TokenPipeEnd::~TokenPipeEnd() 36 : : { 37 [ # # ]: 0 : Close(); 38 : 0 : } 39 : : 40 : 0 : int TokenPipeEnd::TokenWrite(uint8_t token) 41 : : { 42 : 0 : while (true) { 43 : 0 : ssize_t result = write(m_fd, &token, 1); 44 [ # # ]: 0 : if (result < 0) { 45 : : // Failure. It's possible that the write was interrupted by a signal, 46 : : // in that case retry. 47 [ # # ]: 0 : if (errno != EINTR) { 48 : 0 : return TS_ERR; 49 : : } 50 [ # # ]: 0 : } else if (result == 0) { 51 : 0 : return TS_EOS; 52 : : } else { // ==1 53 : 0 : return 0; 54 : : } 55 : : } 56 : 0 : } 57 : : 58 : 0 : int TokenPipeEnd::TokenRead() 59 : : { 60 : : uint8_t token; 61 : 0 : while (true) { 62 : 0 : ssize_t result = read(m_fd, &token, 1); 63 [ # # ]: 0 : if (result < 0) { 64 : : // Failure. Check if the read was interrupted by a signal, 65 : : // in that case retry. 66 [ # # ]: 0 : if (errno != EINTR) { 67 : 0 : return TS_ERR; 68 : : } 69 [ # # ]: 0 : } else if (result == 0) { 70 : 0 : return TS_EOS; 71 : : } else { // ==1 72 : 0 : return token; 73 : : } 74 : : } 75 : : return token; 76 : 0 : } 77 : : 78 : 0 : void TokenPipeEnd::Close() 79 : : { 80 [ # # ]: 0 : if (m_fd != -1) close(m_fd); 81 : 0 : m_fd = -1; 82 : 0 : } 83 : : 84 : 0 : std::optional<TokenPipe> TokenPipe::Make() 85 : : { 86 : 0 : int fds[2] = {-1, -1}; 87 : : #if HAVE_O_CLOEXEC && HAVE_DECL_PIPE2 88 [ # # ]: 0 : if (pipe2(fds, O_CLOEXEC) != 0) { 89 : 0 : return std::nullopt; 90 : : } 91 : : #else 92 : : if (pipe(fds) != 0) { 93 : : return std::nullopt; 94 : : } 95 : : #endif 96 [ # # ]: 0 : return TokenPipe(fds); 97 : 0 : } 98 : : 99 : 0 : TokenPipe::~TokenPipe() 100 : : { 101 [ # # ]: 0 : Close(); 102 : 0 : } 103 : : 104 : 0 : void TokenPipe::Close() 105 : : { 106 [ # # ]: 0 : if (m_fds[0] != -1) close(m_fds[0]); 107 [ # # ]: 0 : if (m_fds[1] != -1) close(m_fds[1]); 108 : 0 : m_fds[0] = m_fds[1] = -1; 109 : 0 : } 110 : : 111 : : #endif // WIN32