commit 81fe1934af666f81b4e6dededba514c7c0b39faa Author: Nick Mathewson nickm@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.",
tor-commits@lists.torproject.org