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