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