commit 77316e9364db0d629354148145f2575fbd835260 Author: Zack Weinberg zackw@cmu.edu Date: Fri Jun 15 13:37:28 2012 -0700
Fix another subtle circuit-teardown bug. --- src/connections.cc | 5 +++-- src/connections.h | 7 +++++-- src/network.cc | 15 +++++++++------ src/protocol/chop.cc | 7 +++++-- src/protocol/null.cc | 1 + 5 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/src/connections.cc b/src/connections.cc index 4f95d12..f252b23 100644 --- a/src/connections.cc +++ b/src/connections.cc @@ -247,6 +247,7 @@ circuit_send(circuit_t *ckt) void circuit_send_eof(circuit_t *ckt) { + ckt->pending_eof_send = true; if (ckt->socks_state) { log_debug(ckt, "EOF during SOCKS phase"); delete ckt; @@ -271,11 +272,11 @@ circuit_recv_eof(circuit_t *ckt) shutdown(bufferevent_getfd(ckt->up_buffer), SHUT_WR); } else { log_debug(ckt, "holding EOF till connection"); - ckt->pending_eof = 1; + ckt->pending_eof_recv = true; } } else { log_debug(ckt, "no buffer, holding EOF till connection"); - ckt->pending_eof = 1; + ckt->pending_eof_recv = true; } }
diff --git a/src/connections.h b/src/connections.h index 64a4252..76c5f56 100644 --- a/src/connections.h +++ b/src/connections.h @@ -121,9 +121,12 @@ struct circuit_t {
bool connected : 1; bool flushing : 1; - bool pending_eof : 1; + bool pending_eof_recv : 1; + bool pending_eof_send : 1;
- circuit_t() : connected(false), flushing(false), pending_eof(false) {} + circuit_t() + : connected(false), flushing(false), + pending_eof_recv(false), pending_eof_send(false) {} virtual ~circuit_t();
/** Return the configuration that this circuit belongs to. */ diff --git a/src/network.cc b/src/network.cc index b5f6d4b..25a05e4 100644 --- a/src/network.cc +++ b/src/network.cc @@ -346,9 +346,11 @@ upstream_event_cb(struct bufferevent *bev, short what, void *arg) /* Upstream is done sending us data. */ circuit_send_eof(ckt); if (bufferevent_get_enabled(bev) || - evbuffer_get_length(bufferevent_get_input(bev)) > 0) { + evbuffer_get_length(bufferevent_get_input(bev)) > 0 || + ckt->pending_eof_send) { log_debug(ckt, "acknowledging EOF upstream"); shutdown(bufferevent_getfd(bev), SHUT_RD); + bufferevent_disable(bev, EV_READ); } else { delete ckt; } @@ -428,11 +430,12 @@ upstream_flush_cb(struct bufferevent *bev, void *arg)
if (remain == 0 && ckt->flushing && ckt->connected && (!ckt->flush_timer || !evtimer_pending(ckt->flush_timer, NULL))) { - bufferevent_disable(bev, EV_WRITE); if (bufferevent_get_enabled(bev) || - evbuffer_get_length(bufferevent_get_input(bev)) > 0) { + evbuffer_get_length(bufferevent_get_input(bev)) > 0 || + ckt->pending_eof_send) { log_debug(ckt, "sending EOF upstream"); shutdown(bufferevent_getfd(bev), SHUT_WR); + bufferevent_disable(bev, EV_WRITE); } else { delete ckt; } @@ -485,7 +488,7 @@ upstream_connect_cb(struct bufferevent *bev, short what, void *arg) upstream_event_cb, ckt); bufferevent_enable(ckt->up_buffer, EV_READ|EV_WRITE); ckt->connected = 1; - if (ckt->pending_eof) { + if (ckt->pending_eof_recv) { /* Try again to process the EOF. */ circuit_recv_eof(ckt); } @@ -530,7 +533,7 @@ downstream_connect_cb(struct bufferevent *bev, short what, void *arg) return; }
- if (ckt->pending_eof) { + if (ckt->pending_eof_recv) { /* Try again to process the EOF. */ circuit_recv_eof(ckt); } @@ -624,7 +627,7 @@ downstream_socks_connect_cb(struct bufferevent *bev, short what, void *arg) connection. */ upstream_read_cb(ckt->up_buffer, ckt);
- if (ckt->pending_eof) { + if (ckt->pending_eof_recv) { /* Try again to process the EOF. */ circuit_recv_eof(ckt); } diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc index a30dd94..65ee661 100644 --- a/src/protocol/chop.cc +++ b/src/protocol/chop.cc @@ -569,6 +569,7 @@ chop_circuit_t::~chop_circuit_t() sent_fin ? '+' : '-', received_fin ? '+' : '-', upstream_eof ? '+' : '-', (unsigned long)downstreams.size()); + *(volatile char *)0 = 0; }
for (unordered_set<chop_conn_t *>::iterator i = downstreams.begin(); @@ -870,9 +871,11 @@ chop_circuit_t::send_targeted(chop_conn_t *conn, size_t d, size_t p, opcode_t f, evbuffer_drain(payload, d);
send_seq++; - if (f == op_FIN) + if (f == op_FIN) { sent_fin = true; - if ((f == op_DAT || f == op_FIN) && d > 0) + pending_eof_send = false; + } + if ((f == op_DAT && d > 0) || f == op_FIN) // We are making forward progress if we are _either_ sending or // receiving data. dead_cycles = 0; diff --git a/src/protocol/null.cc b/src/protocol/null.cc index ca6cc74..dab712a 100644 --- a/src/protocol/null.cc +++ b/src/protocol/null.cc @@ -208,6 +208,7 @@ null_circuit_t::send_eof() { if (this->downstream) conn_send_eof(this->downstream); + this->pending_eof_send = false; return 0; }
tor-commits@lists.torproject.org