summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@ev0ke.net>2015-01-30 14:59:48 -0500
committerDavid Goulet <dgoulet@ev0ke.net>2015-01-30 15:05:18 -0500
commit51f793e37e55b29700f76ca9cdb3199e636bb51d (patch)
treee8d628a7662d51a41258a5215035f0dd5c26873f
parent44e9dafb67370aa6fb163cda150a80466f668111 (diff)
downloadtor-51f793e37e55b29700f76ca9cdb3199e636bb51d.tar.gz
tor-51f793e37e55b29700f76ca9cdb3199e636bb51d.zip
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@ev0ke.net>
-rw-r--r--changes/bug145544
-rw-r--r--src/common/compat_threads.c16
2 files changed, 14 insertions, 6 deletions
diff --git a/changes/bug14554 b/changes/bug14554
new file mode 100644
index 0000000000..ff2566f7af
--- /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 d2d929e430..ff8dc1ca61 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;
}