[tor-commits] [tor/maint-0.2.3] Avoid busy-looping on WANTREAD within connection_handle_write

nickm at torproject.org nickm at torproject.org
Wed Apr 24 16:40:33 UTC 2013


commit 39ac1db60e8b920e1e6b07e08f7f3343960ece79
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Apr 10 19:30:41 2013 -0400

    Avoid busy-looping on WANTREAD within connection_handle_write
    
    Fix for bug 5650.  Also, if we get a WANTREAD while reading while
    writing, make sure we're reading.
---
 changes/bug5650     |    5 +++++
 src/or/connection.c |   17 ++++++++++++++++-
 src/or/or.h         |    3 +++
 3 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/changes/bug5650 b/changes/bug5650
new file mode 100644
index 0000000..401e317
--- /dev/null
+++ b/changes/bug5650
@@ -0,0 +1,5 @@
+  o Major bugfixes:
+    - Avoid a bug where our response to TLS renegotation under certain
+      network conditions could lead to a busy-loop, with 100% CPU
+      consumption. Fixes bug 5650; bugfix on 0.2.0.16-alpha.
+
diff --git a/src/or/connection.c b/src/or/connection.c
index eac9c4f..e366e0e 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -2825,7 +2825,20 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
       case TOR_TLS_WANTWRITE:
         connection_start_writing(conn);
         return 0;
-      case TOR_TLS_WANTREAD: /* we're already reading */
+      case TOR_TLS_WANTREAD:
+        if (conn->in_connection_handle_write) {
+          /* We've been invoked from connection_handle_write, because we're
+           * waiting for a TLS renegotiation, the renegotiation started, and
+           * SSL_read returned WANTWRITE.  But now SSL_read is saying WANTREAD
+           * again.  Stop waiting for write events now, or else we'll
+           * busy-loop until data arrives for us to read. */
+          connection_stop_writing(conn);
+          if (!connection_is_reading(conn))
+            connection_start_reading(conn);
+        }
+        /* we're already reading, one hopes */
+        result = 0;
+        break;
       case TOR_TLS_DONE: /* no data read, so nothing to process */
         result = 0;
         break; /* so we call bucket_decrement below */
@@ -3337,7 +3350,9 @@ connection_handle_write(connection_t *conn, int force)
 {
     int res;
     tor_gettimeofday_cache_clear();
+    conn->in_connection_handle_write = 1;
     res = connection_handle_write_impl(conn, force);
+    conn->in_connection_handle_write = 0;
     return res;
 }
 
diff --git a/src/or/or.h b/src/or/or.h
index 51c23d3..6728b86 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -998,6 +998,9 @@ typedef struct connection_t {
   /** Set to 1 when we're inside connection_flushed_some to keep us from
    * calling connection_handle_write() recursively. */
   unsigned int in_flushed_some:1;
+  /** True if connection_handle_write is currently running on this connection.
+   */
+  unsigned int in_connection_handle_write:1;
 
   /* For linked connections:
    */



More information about the tor-commits mailing list