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