[tor-commits] [tor/master] Fix a bufferevent-related bug that killed tunneled dirserv conns

nickm at torproject.org nickm at torproject.org
Fri Aug 26 20:42:13 UTC 2011


commit 81fe1934af666f81b4e6dededba514c7c0b39faa
Author: Nick Mathewson <nickm at torproject.org>
Date:   Fri Aug 26 16:10:17 2011 -0400

    Fix a bufferevent-related bug that killed tunneled dirserv conns
    
    Because tunneled connections are implemented with buffervent_pair,
    writing to them can cause an immediate flush.  This means that
    added to them and then checking to see whether their outbuf is
    empty is _not_ an adequate way to see whether you added anything.
    This caused a problem in directory server connections, since they
    would try spooling a little more data out, and then close the
    connection if there was no queued data to send.
    
    This fix should improve matters; it only closes the connection if
    there is no more data to spool, and all of the spooling callbacks
    are supposed to put the dirconn into dir_spool_none on completion.
    
    This is bug 3814; Sebastian found it; bugfix on 0.2.3.1-alpha.
---
 changes/bug3814    |    4 ++++
 src/or/directory.c |   17 +++++++++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/changes/bug3814 b/changes/bug3814
new file mode 100644
index 0000000..3db0e3e
--- /dev/null
+++ b/changes/bug3814
@@ -0,0 +1,4 @@
+  o Major bugfixes (bufferevents):
+    - Fix a bug where server-side tunneled bufferevent-based directory
+      streams would get closed prematurely. Fixes 3814, bugfix on
+      0.2.3.1-alpha.
diff --git a/src/or/directory.c b/src/or/directory.c
index 744bc12..c3865ed 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3545,8 +3545,21 @@ connection_dir_finished_flushing(dir_connection_t *conn)
       conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
       return 0;
     case DIR_CONN_STATE_SERVER_WRITING:
-      log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
-      connection_mark_for_close(TO_CONN(conn));
+      if (conn->dir_spool_src != DIR_SPOOL_NONE) {
+#ifdef USE_BUFFEREVENTS
+        /* This can happen with paired bufferevents, since a paired connection
+         * can flush immediately when you write to it, making the subsequent
+         * check in connection_handle_write_cb() decide that the connection
+         * is flushed. */
+        log_debug(LD_DIRSERV, "Emptied a dirserv buffer, but still spooling.");
+#else
+        log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
+        connection_mark_for_close(TO_CONN(conn));
+#endif
+      } else {
+        log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
+        connection_mark_for_close(TO_CONN(conn));
+      }
       return 0;
     default:
       log_warn(LD_BUG,"called in unexpected state %d.",





More information about the tor-commits mailing list