Browse Source

Merge remote-tracking branch 'public/bug5650_squashed' into maint-0.2.4

Nick Mathewson 11 years ago
parent
commit
97246a5b6d
3 changed files with 24 additions and 1 deletions
  1. 5 0
      changes/bug5650
  2. 16 1
      src/or/connection.c
  3. 3 0
      src/or/or.h

+ 5 - 0
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.
+

+ 16 - 1
src/or/connection.c

@@ -2954,7 +2954,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 */
@@ -3513,7 +3526,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;
 }
 

+ 3 - 0
src/or/or.h

@@ -1163,6 +1163,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:
    */