summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-08-26 16:10:17 -0400
committerNick Mathewson <nickm@torproject.org>2011-08-26 16:10:17 -0400
commit81fe1934af666f81b4e6dededba514c7c0b39faa (patch)
tree090f2d333acf1346c57ee3c676f0f936b1457bce
parentb161674d5dc312f95a495bed3c25d892fc9f0550 (diff)
downloadtor-81fe1934af666f81b4e6dededba514c7c0b39faa.tar.gz
tor-81fe1934af666f81b4e6dededba514c7c0b39faa.zip
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.
-rw-r--r--changes/bug38144
-rw-r--r--src/or/directory.c17
2 files changed, 19 insertions, 2 deletions
diff --git a/changes/bug3814 b/changes/bug3814
new file mode 100644
index 0000000000..3db0e3ef75
--- /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 744bc120fb..c3865eda85 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.",