aboutsummaryrefslogtreecommitdiff
path: root/src/common/compat_threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/compat_threads.c')
-rw-r--r--src/common/compat_threads.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c
index 98bdbbcf5e..024c627cf1 100644
--- a/src/common/compat_threads.c
+++ b/src/common/compat_threads.c
@@ -40,6 +40,7 @@ tor_mutex_free(tor_mutex_t *m)
tor_free(m);
}
+/** Allocate and return a new condition variable. */
tor_cond_t *
tor_cond_new(void)
{
@@ -48,6 +49,8 @@ tor_cond_new(void)
tor_free(cond);
return cond;
}
+
+/** Free all storage held in <b>c</b>. */
void
tor_cond_free(tor_cond_t *c)
{
@@ -140,13 +143,16 @@ sock_drain(tor_socket_t fd)
return 0;
}
-/** Allocate a new set of alert sockets. DOCDOC */
+/** Allocate a new set of alert sockets, and set the appropriate function
+ * pointers, in <b>socks_out</b>. */
int
alert_sockets_create(alert_sockets_t *socks_out)
{
tor_socket_t socks[2];
#ifdef HAVE_EVENTFD
+ /* First, we try the Linux eventfd() syscall. This gives a 64-bit counter
+ * associated with a single file descriptor. */
#if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
socks[0] = eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);
#else
@@ -171,6 +177,8 @@ alert_sockets_create(alert_sockets_t *socks_out)
#endif
#ifdef HAVE_PIPE2
+ /* Now we're going to try pipes. First type the pipe2() syscall, if we
+ * have it, so we can save some calls... */
if (pipe2(socks, O_NONBLOCK|O_CLOEXEC) == 0) {
socks_out->read_fd = socks[0];
socks_out->write_fd = socks[1];
@@ -181,6 +189,8 @@ alert_sockets_create(alert_sockets_t *socks_out)
#endif
#ifdef HAVE_PIPE
+ /* Now try the regular pipe() syscall. Pipes have a bit lower overhead than
+ * socketpairs, fwict. */
if (pipe(socks) == 0) {
if (fcntl(socks[0], F_SETFD, FD_CLOEXEC) < 0 ||
fcntl(socks[1], F_SETFD, FD_CLOEXEC) < 0 ||
@@ -198,12 +208,35 @@ alert_sockets_create(alert_sockets_t *socks_out)
}
#endif
+ /* If nothing else worked, fall back on socketpair(). */
if (tor_socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == 0) {
- set_socket_nonblocking(socks[0]);
- set_socket_nonblocking(socks[1]);
+ if (set_socket_nonblocking(socks[0]) < 0 ||
+ set_socket_nonblocking(socks[1])) {
+ tor_close_socket(socks[0]);
+ tor_close_socket(socks[1]);
+ return -1;
+ }
+ socks_out->read_fd = socks[0];
+ socks_out->write_fd = socks[1];
socks_out->alert_fn = sock_alert;
socks_out->drain_fn = sock_drain;
return 0;
}
return -1;
}
+
+/** Close the sockets in <b>socks</b>. */
+void
+alert_sockets_close(alert_sockets_t *socks)
+{
+ if (socks->alert_fn == sock_alert) {
+ /* they are sockets. */
+ tor_close_socket(socks->read_fd);
+ tor_close_socket(socks->write_fd);
+ } else {
+ close(socks->read_fd);
+ if (socks->write_fd != socks->read_fd)
+ close(socks->write_fd);
+ }
+ socks->read_fd = socks->write_fd = -1;
+}