[tor-commits] [tor/master] handle EINTR in compat_*threads.c

nickm at torproject.org nickm at torproject.org
Wed Jan 21 19:50:31 UTC 2015


commit ac5b70c700b211008853b5f212100a867f508dfd
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Jan 21 12:18:11 2015 -0500

    handle EINTR in compat_*threads.c
---
 src/common/compat_pthreads.c |   40 ++++++++++++++++++++----------
 src/common/compat_threads.c  |   55 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 78 insertions(+), 17 deletions(-)

diff --git a/src/common/compat_pthreads.c b/src/common/compat_pthreads.c
index f434805..188a91f 100644
--- a/src/common/compat_pthreads.c
+++ b/src/common/compat_pthreads.c
@@ -196,23 +196,37 @@ tor_cond_uninit(tor_cond_t *cond)
 int
 tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv)
 {
+  int r;
   if (tv == NULL) {
-    return pthread_cond_wait(&cond->cond, &mutex->mutex) ? -1 : 0;
+    while (1) {
+      r = pthread_cond_wait(&cond->cond, &mutex->mutex);
+      if (r == EINTR) {
+        /* EINTR should be impossible according to POSIX, but POSIX, like the
+         * Pirate's Code, is apparently treated "more like what you'd call
+         * guidelines than actual rules." */
+        continue;
+      }
+      return r ? -1 : 0;
+    }
   } else {
     struct timespec ts;
     struct timeval tvnow, tvsum;
-    int r;
-    gettimeofday(&tvnow, NULL);
-    timeradd(tv, &tvnow, &tvsum);
-    ts.tv_sec = tvsum.tv_sec;
-    ts.tv_nsec = tvsum.tv_usec * 1000;
-    r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts);
-    if (r == 0)
-      return 0;
-    else if (r == ETIMEDOUT)
-      return 1;
-    else
-      return -1;
+    while (1) {
+      gettimeofday(&tvnow, NULL);
+      timeradd(tv, &tvnow, &tvsum);
+      ts.tv_sec = tvsum.tv_sec;
+      ts.tv_nsec = tvsum.tv_usec * 1000;
+
+      r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts);
+      if (r == 0)
+        return 0;
+      else if (r == ETIMEDOUT)
+        return 1;
+      else if (r == EINTR)
+        continue;
+      else
+        return -1;
+    }
   }
 }
 /** Wake up one of the waiters on <b>cond</b>. */
diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c
index 7944007..3b79292 100644
--- a/src/common/compat_threads.c
+++ b/src/common/compat_threads.c
@@ -88,12 +88,59 @@ in_main_thread(void)
   return main_thread_id == tor_get_thread_id();
 }
 
+#if defined(HAVE_EVENTFD) || defined(HAVE_PIPE)
+/* non-interruptable versions */
+static int
+write_ni(int fd, const void *buf, size_t n)
+{
+  int r;
+ again:
+  r = write(fd, buf, n);
+  if (r < 0 && errno == EINTR)
+    goto again;
+  return r;
+}
+static int
+read_ni(int fd, void *buf, size_t n)
+{
+  int r;
+ again:
+  r = read(fd, buf, n);
+  if (r < 0 && errno == EINTR)
+    goto again;
+  return r;
+}
+#endif
+
+/* non-interruptable versions */
+static int
+send_ni(int fd, const void *buf, size_t n, int flags)
+{
+  int r;
+ again:
+  r = send(fd, buf, n, flags);
+  if (r < 0 && errno == EINTR)
+    goto again;
+  return r;
+}
+
+static int
+recv_ni(int fd, void *buf, size_t n, int flags)
+{
+  int r;
+ again:
+   r = recv(fd, buf, n, flags);
+  if (r < 0 && errno == EINTR)
+    goto again;
+  return r;
+}
+
 #ifdef HAVE_EVENTFD
 static int
 eventfd_alert(int fd)
 {
   uint64_t u = 1;
-  int r = write(fd, (void*)&u, sizeof(u));
+  int r = write_ni(fd, (void*)&u, sizeof(u));
   if (r < 0 && errno != EAGAIN)
     return -1;
   return 0;
@@ -103,7 +150,7 @@ static int
 eventfd_drain(int fd)
 {
   uint64_t u = 0;
-  int r = read(fd, (void*)&u, sizeof(u));
+  int r = read_ni(fd, (void*)&u, sizeof(u));
   if (r < 0 && errno != EAGAIN)
     return -1;
   return 0;
@@ -136,7 +183,7 @@ pipe_drain(int fd)
 static int
 sock_alert(tor_socket_t fd)
 {
-  ssize_t r = send(fd, "x", 1, 0);
+  ssize_t r = send_ni(fd, "x", 1, 0);
   if (r < 0 && !ERRNO_IS_EAGAIN(tor_socket_errno(fd)))
     return -1;
   return 0;
@@ -147,7 +194,7 @@ sock_drain(tor_socket_t fd)
 {
   char buf[32];
   ssize_t r;
-  while ((r = recv(fd, buf, sizeof(buf), 0)) >= 0)
+  while ((r = recv_ni(fd, buf, sizeof(buf), 0)) >= 0)
     ;
   if (r == 0 || !ERRNO_IS_EAGAIN(tor_socket_errno(fd)))
     return -1;





More information about the tor-commits mailing list