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