[tor-commits] [tor/master] Fix possible infinite loop on pipe/sock_drain()

nickm at torproject.org nickm at torproject.org
Fri Jan 30 20:37:12 UTC 2015


commit 51f793e37e55b29700f76ca9cdb3199e636bb51d
Author: David Goulet <dgoulet at ev0ke.net>
Date:   Fri Jan 30 14:59:48 2015 -0500

    Fix possible infinite loop on pipe/sock_drain()
    
    If the returned value of read/recv is 0 (meaning EOF), we'll end up in an
    infinite loop (active wait) until something is written on the pipe which is
    not really what we want here especially because those functions are called
    from the main thread.
    
    Signed-off-by: David Goulet <dgoulet at ev0ke.net>
---
 changes/bug14554            |    4 ++++
 src/common/compat_threads.c |   16 ++++++++++------
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/changes/bug14554 b/changes/bug14554
new file mode 100644
index 0000000..ff2566f
--- /dev/null
+++ b/changes/bug14554
@@ -0,0 +1,4 @@
+  o Major bugfix
+    - Possibility of an infinite loop if the returned value of the read/recv
+      was 0. A returned value of 0 means that we've reached the EOF thus the
+      pipe/sock is drained so return success not an error.
diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c
index d2d929e..ff8dc1c 100644
--- a/src/common/compat_threads.c
+++ b/src/common/compat_threads.c
@@ -171,10 +171,12 @@ pipe_drain(int fd)
 {
   char buf[32];
   ssize_t r;
-  while ((r = read_ni(fd, buf, sizeof(buf))) >= 0)
-    ;
-  if (r == 0 || errno != EAGAIN)
+  do {
+    r = read_ni(fd, buf, sizeof(buf));
+  } while (r > 0);
+  if (errno != EAGAIN)
     return -1;
+  /* A value of r = 0 means EOF on the fd so successfully drained. */
   return 0;
 }
 #endif
@@ -193,10 +195,12 @@ sock_drain(tor_socket_t fd)
 {
   char buf[32];
   ssize_t r;
-  while ((r = recv_ni(fd, buf, sizeof(buf), 0)) >= 0)
-    ;
-  if (r == 0 || !ERRNO_IS_EAGAIN(tor_socket_errno(fd)))
+  do {
+    r = recv_ni(fd, buf, sizeof(buf), 0);
+  } while (r > 0);
+  if (!ERRNO_IS_EAGAIN(tor_socket_errno(fd)))
     return -1;
+  /* A value of r = 0 means EOF on the fd so successfully drained. */
   return 0;
 }
 





More information about the tor-commits mailing list