Branch data Line data Source code
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 : 1891 : TokenPipeEnd TokenPipe::TakeReadEnd()
19 : : {
20 : 1891 : TokenPipeEnd res(m_fds[0]);
21 : 1891 : m_fds[0] = -1;
22 : 1891 : return res;
23 : : }
24 : :
25 : 1891 : TokenPipeEnd TokenPipe::TakeWriteEnd()
26 : : {
27 : 1891 : TokenPipeEnd res(m_fds[1]);
28 : 1891 : m_fds[1] = -1;
29 : 1891 : return res;
30 : : }
31 : :
32 : 8739 : TokenPipeEnd::TokenPipeEnd(int fd) : m_fd(fd)
33 : : {
34 : 8739 : }
35 : :
36 : 8737 : TokenPipeEnd::~TokenPipeEnd()
37 : : {
38 : 8737 : Close();
39 : 8737 : }
40 : :
41 : 1036 : int TokenPipeEnd::TokenWrite(uint8_t token)
42 : : {
43 : 1036 : while (true) {
44 : 1036 : ssize_t result = write(m_fd, &token, 1);
45 [ - + ]: 1036 : 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 : : return TS_ERR;
50 : : }
51 [ + - ]: 1036 : } else if (result == 0) {
52 : : return TS_EOS;
53 : : } else { // ==1
54 : 1036 : return 0;
55 : : }
56 : : }
57 : : }
58 : :
59 : 1035 : int TokenPipeEnd::TokenRead()
60 : : {
61 : 1042 : uint8_t token;
62 : 1042 : while (true) {
63 : 1042 : ssize_t result = read(m_fd, &token, 1);
64 [ + + ]: 1042 : 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 : : return TS_ERR;
69 : : }
70 [ + - ]: 1035 : } else if (result == 0) {
71 : : return TS_EOS;
72 : : } else { // ==1
73 : 1035 : return token;
74 : : }
75 : : }
76 : : return token;
77 : : }
78 : :
79 : 12519 : void TokenPipeEnd::Close()
80 : : {
81 [ + + ]: 12519 : if (m_fd != -1) close(m_fd);
82 : 12519 : m_fd = -1;
83 : 12519 : }
84 : :
85 : 1891 : std::optional<TokenPipe> TokenPipe::Make()
86 : : {
87 : 1891 : int fds[2] = {-1, -1};
88 : : #if HAVE_O_CLOEXEC && HAVE_DECL_PIPE2
89 [ - + ]: 1891 : if (pipe2(fds, O_CLOEXEC) != 0) {
90 : 0 : return std::nullopt;
91 : : }
92 : : #else
93 : : if (pipe(fds) != 0) {
94 : : return std::nullopt;
95 : : }
96 : : #endif
97 : 3782 : return TokenPipe(fds);
98 : : }
99 : :
100 : 3782 : TokenPipe::~TokenPipe()
101 : : {
102 : 3782 : Close();
103 : 3782 : }
104 : :
105 : 3782 : void TokenPipe::Close()
106 : : {
107 [ - + ]: 3782 : if (m_fds[0] != -1) close(m_fds[0]);
108 [ - + ]: 3782 : if (m_fds[1] != -1) close(m_fds[1]);
109 : 3782 : m_fds[0] = m_fds[1] = -1;
110 : 3782 : }
111 : :
112 : : #endif // WIN32
|