diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 5b24425877..e742a5614f 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -1986,6 +1986,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
"No intro points for '%s': re-fetching service descriptor.",
safe_str_client(rend_data->onion_address));
rend_client_refetch_v2_renddesc(rend_data);
+ connection_ap_mark_as_non_pending_circuit(conn);
ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_RENDDESC_WAIT;
return 0;
}
diff --git a/src/or/connection.c b/src/or/connection.c
index 78176d3768..b31b99c2e7 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1597,6 +1597,8 @@ connection_init_accepted_conn(connection_t *conn,
break;
case CONN_TYPE_AP_TRANS_LISTENER:
TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
+ /* XXXX028 -- is this correct still, with the addition of
+ * pending_entry_connections ? */
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
return connection_ap_process_transparent(TO_ENTRY_CONN(conn));
case CONN_TYPE_AP_NATD_LISTENER:
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 078b9e2f48..30dcd13f4a 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -771,7 +771,7 @@ connection_ap_rescan_and_attach_pending(void)
"adding it.",
pending_entry_connections);
untried_pending_connections = 1;
- smartlist_add(pending_entry_connections, entry_conn);
+ connection_ap_mark_as_pending_circuit(entry_conn);
}
} SMARTLIST_FOREACH_END(conn);
@@ -827,8 +827,11 @@ connection_ap_attach_pending(int retry)
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT) {
SMARTLIST_DEL_CURRENT(pending_entry_connections, entry_conn);
+ continue;
}
+ tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
+
} SMARTLIST_FOREACH_END(entry_conn);
untried_pending_connections = 0;
@@ -847,6 +850,7 @@ connection_ap_mark_as_pending_circuit_(entry_connection_t *entry_conn,
{
connection_t *conn = ENTRY_TO_CONN(entry_conn);
tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
if (conn->marked_for_close)
return;
@@ -866,6 +870,15 @@ connection_ap_mark_as_pending_circuit_(entry_connection_t *entry_conn,
smartlist_add(pending_entry_connections, entry_conn);
}
+/** Mark entry_conn as no longer waiting for a circuit. */
+void
+connection_ap_mark_as_non_pending_circuit(entry_connection_t *entry_conn)
+{
+ if (PREDICT_UNLIKELY(NULL == pending_entry_connections))
+ return;
+ smartlist_remove(pending_entry_connections, entry_conn);
+}
+
/** Tell any AP streams that are waiting for a one-hop tunnel to
* failed_digest that they are going to fail. */
/* XXX024 We should get rid of this function, and instead attach
@@ -986,6 +999,7 @@ connection_ap_detach_retriable(entry_connection_t *conn,
circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
connection_ap_mark_as_pending_circuit(conn);
} else {
+ CONNECTION_AP_EXPECT_NONPENDING(conn);
ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
}
@@ -1038,6 +1052,7 @@ connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn,
const or_options_t *options = get_options();
if (options->LeaveStreamsUnattached) {
+ CONNECTION_AP_EXPECT_NONPENDING(conn);
ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
return 0;
}
@@ -1689,6 +1704,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
* Also, a fetch could have been requested if the onion address was not
* found in the cache previously. */
if (refetch_desc || !rend_client_any_intro_points_usable(entry)) {
+ connection_ap_mark_as_non_pending_circuit(conn);
base_conn->state = AP_CONN_STATE_RENDDESC_WAIT;
log_info(LD_REND, "Unknown descriptor %s. Fetching.",
safe_str_client(rend_data->onion_address));
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 90cf2a350f..6da51eb0c6 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -70,6 +70,14 @@ void connection_ap_mark_as_pending_circuit_(entry_connection_t *entry_conn,
const char *file, int line);
#define connection_ap_mark_as_pending_circuit(c) \
connection_ap_mark_as_pending_circuit_((c), __FILE__, __LINE__)
+void connection_ap_mark_as_non_pending_circuit(entry_connection_t *entry_conn);
+#define CONNECTION_AP_EXPECT_NONPENDING(c) do { \
+ if (ENTRY_TO_CONN(c)->state == AP_CONN_STATE_CIRCUIT_WAIT) { \
+ log_warn(LD_BUG, "At %s:%d: %p was unexpectedly in circuit_wait.", \
+ __FILE__, __LINE__, (c)); \
+ connection_ap_mark_as_non_pending_circuit(c); \
+ } \
+ } while (0)
void connection_ap_fail_onehop(const char *failed_digest,
cpath_build_state_t *build_state);
void circuit_discard_optional_exit_enclaves(extend_info_t *info);
diff --git a/src/or/control.c b/src/or/control.c
index f2eab7b352..34d03befa6 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -3011,6 +3011,7 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
edge_conn->end_reason = 0;
if (tmpcirc)
circuit_detach_stream(tmpcirc, edge_conn);
+ CONNECTION_AP_EXPECT_NONPENDING(ap_conn);
TO_CONN(edge_conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
}
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index f7710908bd..ded0d8431b 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -125,6 +125,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
/* Make a new dummy AP connection, and attach the request to it. */
entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ CONNECTION_AP_EXPECT_NONPENDING(entry_conn);
TO_CONN(conn)->state = AP_CONN_STATE_RESOLVE_WAIT;
conn->is_dns_request = 1;
@@ -199,6 +200,7 @@ dnsserv_launch_request(const char *name, int reverse,
/* Make a new dummy AP connection, and attach the request to it. */
entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ CONNECTION_AP_EXPECT_NONPENDING(entry_conn);
conn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
tor_addr_copy(&TO_CONN(conn)->addr, &control_conn->base_.addr);
diff --git a/src/or/relay.c b/src/or/relay.c
index eddad6a0cb..aed6bf7009 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1304,6 +1304,7 @@ connection_edge_process_relay_cell_not_open(
"Got 'connected' while not in state connect_wait. Dropping.");
return 0;
}
+ CONNECTION_AP_EXPECT_NONPENDING(entry_conn);
conn->base_.state = AP_CONN_STATE_OPEN;
log_info(LD_APP,"'connected' received for circid %u streamid %d "
"after %d seconds.",
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 3e1c4f3613..d9cea53c04 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -173,6 +173,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT,
introcirc->rend_data->onion_address))) {
+ connection_ap_mark_as_non_pending_circuit(TO_ENTRY_CONN(conn));
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
}
}
@@ -1055,9 +1056,11 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
rend_client_refetch_v2_renddesc(rend_query);
/* move all pending streams back to renddesc_wait */
+ /* NOTE: We can now do this faster, if we use pending_entry_connections */
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT,
rend_query->onion_address))) {
+ connection_ap_mark_as_non_pending_circuit(TO_ENTRY_CONN(conn));
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
}