Tor 0.4.9.0-alpha-dev
alertsock.c
Go to the documentation of this file.
1/* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6/**
7 * \file alertsock.c
8 *
9 * \brief Use a socket to alert the main thread from a worker thread.
10 *
11 * Because our main loop spends all of its time in select, epoll, kqueue, or
12 * etc, we need a way to wake up the main loop from another thread. This code
13 * tries to provide the fastest reasonable way to do that, depending on our
14 * platform.
15 **/
16
17#include "orconfig.h"
18#include "lib/net/alertsock.h"
19#include "lib/net/socket.h"
20#include "lib/log/util_bug.h"
21
22#ifdef HAVE_SYS_EVENTFD_H
23#include <sys/eventfd.h>
24#endif
25#ifdef HAVE_FCNTL_H
26#include <fcntl.h>
27#endif
28#ifdef HAVE_UNISTD_H
29#include <unistd.h>
30#endif
31#ifdef HAVE_SYS_SOCKET_H
32#include <sys/socket.h>
33#endif
34#ifdef _WIN32
35#include <winsock2.h>
36#endif
37
38#if defined(HAVE_EVENTFD) || defined(HAVE_PIPE)
39/* As write(), but retry on EINTR, and return the negative error code on
40 * error. */
41static int
42write_ni(int fd, const void *buf, size_t n)
43{
44 int r;
45 again:
46 r = (int) write(fd, buf, n);
47 if (r < 0) {
48 if (errno == EINTR)
49 goto again;
50 else
51 return -errno;
52 }
53 return r;
54}
55/* As read(), but retry on EINTR, and return the negative error code on error.
56 */
57static int
58read_ni(int fd, void *buf, size_t n)
59{
60 int r;
61 again:
62 r = (int) read(fd, buf, n);
63 if (r < 0) {
64 if (errno == EINTR)
65 goto again;
66 else
67 return -errno;
68 }
69 return r;
70}
71#endif /* defined(HAVE_EVENTFD) || defined(HAVE_PIPE) */
72
73/** As send(), but retry on EINTR, and return the negative error code on
74 * error. */
75static int
76send_ni(int fd, const void *buf, size_t n, int flags)
77{
78 int r;
79 again:
80 r = (int) send(fd, buf, n, flags);
81 if (r < 0) {
82 int error = tor_socket_errno(fd);
83 if (ERRNO_IS_EINTR(error))
84 goto again;
85 else
86 return -error;
87 }
88 return r;
89}
90
91/** As recv(), but retry on EINTR, and return the negative error code on
92 * error. */
93static int
94recv_ni(int fd, void *buf, size_t n, int flags)
95{
96 int r;
97 again:
98 r = (int) recv(fd, buf, n, flags);
99 if (r < 0) {
100 int error = tor_socket_errno(fd);
101 if (ERRNO_IS_EINTR(error))
102 goto again;
103 else
104 return -error;
105 }
106 return r;
107}
108
109#ifdef HAVE_EVENTFD
110/* Increment the event count on an eventfd <b>fd</b> */
111static int
112eventfd_alert(int fd)
113{
114 uint64_t u = 1;
115 int r = write_ni(fd, (void*)&u, sizeof(u));
116 if (r < 0 && -r != EAGAIN)
117 return -1;
118 return 0;
119}
120
121/* Drain all events from an eventfd <b>fd</b>. */
122static int
123eventfd_drain(int fd)
124{
125 uint64_t u = 0;
126 int r = read_ni(fd, (void*)&u, sizeof(u));
127 if (r < 0 && -r != EAGAIN)
128 return r;
129 return 0;
130}
131#endif /* defined(HAVE_EVENTFD) */
132
133#ifdef HAVE_PIPE
134/** Send a byte over a pipe. Return 0 on success or EAGAIN; -1 on error */
135static int
136pipe_alert(int fd)
137{
138 ssize_t r = write_ni(fd, "x", 1);
139 if (r < 0 && -r != EAGAIN)
140 return (int)r;
141 return 0;
142}
143
144/** Drain all input from a pipe <b>fd</b> and ignore it. Return 0 on
145 * success, -1 on error. */
146static int
147pipe_drain(int fd)
148{
149 char buf[32];
150 ssize_t r;
151 do {
152 r = read_ni(fd, buf, sizeof(buf));
153 } while (r > 0);
154 if (r < 0 && errno != EAGAIN)
155 return -errno;
156 /* A value of r = 0 means EOF on the fd so successfully drained. */
157 return 0;
158}
159#endif /* defined(HAVE_PIPE) */
160
161/** Send a byte on socket <b>fd</b>t. Return 0 on success or EAGAIN,
162 * -1 on error. */
163static int
165{
166 ssize_t r = send_ni(fd, "x", 1, 0);
167 if (r < 0 && !ERRNO_IS_EAGAIN(-r))
168 return (int)r;
169 return 0;
170}
171
172/** Drain all the input from a socket <b>fd</b>, and ignore it. Return 0 on
173 * success, -errno on error. */
174static int
176{
177 char buf[32];
178 ssize_t r;
179 do {
180 r = recv_ni(fd, buf, sizeof(buf), 0);
181 } while (r > 0);
182 if (r < 0 && !ERRNO_IS_EAGAIN(-r))
183 return (int)r;
184 /* A value of r = 0 means EOF on the fd so successfully drained. */
185 return 0;
186}
187
188/** Allocate a new set of alert sockets, and set the appropriate function
189 * pointers, in <b>socks_out</b>. */
190int
191alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags)
192{
194
195#ifdef HAVE_EVENTFD
196 /* First, we try the Linux eventfd() syscall. This gives a 64-bit counter
197 * associated with a single file descriptor. */
198#if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
199 if (!(flags & ASOCKS_NOEVENTFD2))
200 socks[0] = eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);
201#endif
202 if (socks[0] < 0 && !(flags & ASOCKS_NOEVENTFD)) {
203 socks[0] = eventfd(0,0);
204 if (socks[0] >= 0) {
205 if (fcntl(socks[0], F_SETFD, FD_CLOEXEC) < 0 ||
206 set_socket_nonblocking(socks[0]) < 0) {
207 // LCOV_EXCL_START -- if eventfd succeeds, fcntl will.
209 close(socks[0]);
210 return -1;
211 // LCOV_EXCL_STOP
212 }
213 }
214 }
215 if (socks[0] >= 0) {
216 socks_out->read_fd = socks_out->write_fd = socks[0];
217 socks_out->alert_fn = eventfd_alert;
218 socks_out->drain_fn = eventfd_drain;
219 return 0;
220 }
221#endif /* defined(HAVE_EVENTFD) */
222
223#ifdef HAVE_PIPE2
224 /* Now we're going to try pipes. First type the pipe2() syscall, if we
225 * have it, so we can save some calls... */
226 if (!(flags & ASOCKS_NOPIPE2) &&
227 pipe2(socks, O_NONBLOCK|O_CLOEXEC) == 0) {
228 socks_out->read_fd = socks[0];
229 socks_out->write_fd = socks[1];
230 socks_out->alert_fn = pipe_alert;
231 socks_out->drain_fn = pipe_drain;
232 return 0;
233 }
234#endif /* defined(HAVE_PIPE2) */
235
236#ifdef HAVE_PIPE
237 /* Now try the regular pipe() syscall. Pipes have a bit lower overhead than
238 * socketpairs, fwict. */
239 if (!(flags & ASOCKS_NOPIPE) &&
240 pipe(socks) == 0) {
241 if (fcntl(socks[0], F_SETFD, FD_CLOEXEC) < 0 ||
242 fcntl(socks[1], F_SETFD, FD_CLOEXEC) < 0 ||
243 set_socket_nonblocking(socks[0]) < 0 ||
244 set_socket_nonblocking(socks[1]) < 0) {
245 // LCOV_EXCL_START -- if pipe succeeds, you can fcntl the output
247 close(socks[0]);
248 close(socks[1]);
249 return -1;
250 // LCOV_EXCL_STOP
251 }
252 socks_out->read_fd = socks[0];
253 socks_out->write_fd = socks[1];
254 socks_out->alert_fn = pipe_alert;
255 socks_out->drain_fn = pipe_drain;
256 return 0;
257 }
258#endif /* defined(HAVE_PIPE) */
259
260 /* If nothing else worked, fall back on socketpair(). */
261 if (!(flags & ASOCKS_NOSOCKETPAIR) &&
262 tor_socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == 0) {
263 if (set_socket_nonblocking(socks[0]) < 0 ||
264 set_socket_nonblocking(socks[1])) {
265 // LCOV_EXCL_START -- if socketpair worked, you can make it nonblocking.
267 tor_close_socket(socks[0]);
268 tor_close_socket(socks[1]);
269 return -1;
270 // LCOV_EXCL_STOP
271 }
272 socks_out->read_fd = socks[0];
273 socks_out->write_fd = socks[1];
274 socks_out->alert_fn = sock_alert;
275 socks_out->drain_fn = sock_drain;
276 return 0;
277 }
278 return -1;
279}
280
281/** Close the sockets in <b>socks</b>. */
282void
284{
285 if (socks->alert_fn == sock_alert) {
286 /* they are sockets. */
289 } else {
290 close(socks->read_fd);
291 if (socks->write_fd != socks->read_fd)
292 close(socks->write_fd);
293 }
294 socks->read_fd = socks->write_fd = -1;
295}
int alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags)
Definition: alertsock.c:191
static int recv_ni(int fd, void *buf, size_t n, int flags)
Definition: alertsock.c:94
static int sock_alert(tor_socket_t fd)
Definition: alertsock.c:164
static int sock_drain(tor_socket_t fd)
Definition: alertsock.c:175
void alert_sockets_close(alert_sockets_t *socks)
Definition: alertsock.c:283
static int send_ni(int fd, const void *buf, size_t n, int flags)
Definition: alertsock.c:76
Header for alertsock.c.
#define TOR_INVALID_SOCKET
Definition: nettypes.h:41
#define tor_socket_t
Definition: nettypes.h:36
int tor_close_socket(tor_socket_t s)
Definition: socket.c:217
int set_socket_nonblocking(tor_socket_t sock)
Definition: socket.c:560
int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
Definition: socket.c:469
Header for socket.c.
int(* alert_fn)(tor_socket_t write_fd)
Definition: alertsock.h:30
tor_socket_t read_fd
Definition: alertsock.h:26
tor_socket_t write_fd
Definition: alertsock.h:28
int(* drain_fn)(tor_socket_t read_fd)
Definition: alertsock.h:32
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:177