diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 68a0eca5dd..d9da7a9728 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -103,7 +103,7 @@ circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
tor_free(found);
--old_conn->n_circuits;
}
- if (active)
+ if (active && old_conn != conn)
make_circuit_inactive_on_conn(circ,old_conn);
}
@@ -123,7 +123,7 @@ circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
found->circuit = circ;
HT_INSERT(orconn_circid_map, &orconn_circid_circuit_map, found);
}
- if (active)
+ if (active && old_conn != conn)
make_circuit_active_on_conn(circ,conn);
++conn->n_circuits;
@@ -145,6 +145,7 @@ circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
circ->p_circ_id = id;
circ->p_conn = conn;
active = circ->p_conn_cells.n > 0;
+ tor_assert(bool_eq(active, circ->next_active_on_p_conn));
if (id == old_id && conn == old_conn)
return;
@@ -168,6 +169,7 @@ circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
circ->n_circ_id = id;
circ->n_conn = conn;
active = circ->n_conn_cells.n > 0;
+ tor_assert(bool_eq(active, circ->next_active_on_n_conn));
if (id == old_id && conn == old_conn)
return;
diff --git a/src/or/relay.c b/src/or/relay.c
index bbb9df65db..7d853124a6 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1470,6 +1470,13 @@ circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint)
* cells. */
#define CELL_QUEUE_LOWWATER_SIZE 64
+#ifdef ACTIVE_CIRCUITS_PARANOIA
+#define assert_active_circuits_ok_paranoid(conn) \
+ assert_active_circuits_ok(conn)
+#else
+#define assert_active_circuits_ok_paranoid(conn)
+#endif
+
/** Release storage held by cell */
static INLINE void
cell_free(cell_t *cell)
@@ -1546,6 +1553,8 @@ cell_queue_pop(cell_queue_t *queue)
static INLINE circuit_t **
next_circ_on_conn_p(circuit_t *circ, or_connection_t *conn)
{
+ tor_assert(circ);
+ tor_assert(conn);
if (conn == circ->n_conn) {
return &circ->next_active_on_n_conn;
} else {
@@ -1560,6 +1569,8 @@ next_circ_on_conn_p(circuit_t *circ, or_connection_t *conn)
static INLINE circuit_t **
prev_circ_on_conn_p(circuit_t *circ, or_connection_t *conn)
{
+ tor_assert(circ);
+ tor_assert(conn);
if (conn == circ->n_conn) {
return &circ->prev_active_on_n_conn;
} else {
@@ -1589,6 +1600,7 @@ make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn)
*prev_circ_on_conn_p(head, conn) = circ;
*prev_circ_on_conn_p(circ, conn) = old_tail;
}
+ assert_active_circuits_ok_paranoid(conn);
}
/** Remove circ to the list of circuits with pending cells on
@@ -1598,6 +1610,7 @@ make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn)
{
circuit_t *next = *next_circ_on_conn_p(circ, conn);
circuit_t *prev = *prev_circ_on_conn_p(circ, conn);
+ tor_assert(next && prev);
tor_assert(*prev_circ_on_conn_p(next, conn) == circ);
tor_assert(*next_circ_on_conn_p(prev, conn) == circ);
@@ -1611,6 +1624,7 @@ make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn)
}
*prev_circ_on_conn_p(circ, conn) = NULL;
*next_circ_on_conn_p(circ, conn) = NULL;
+ assert_active_circuits_ok_paranoid(conn);
}
/** Remove all circuits from the list of circuits with pending cells on
@@ -1677,6 +1691,7 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max)
int streams_blocked;
circ = conn->active_circuits;
if (!circ) return 0;
+ assert_active_circuits_ok_paranoid(conn);
if (circ->n_conn == conn) {
queue = &circ->n_conn_cells;
streams_blocked = circ->streams_blocked_on_n_conn;
@@ -1684,14 +1699,27 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max)
queue = &TO_OR_CIRCUIT(circ)->p_conn_cells;
streams_blocked = circ->streams_blocked_on_p_conn;
}
+ tor_assert(*next_circ_on_conn_p(circ,conn));
for (n_flushed = 0; n_flushed < max && queue->head; ++n_flushed) {
cell_t *cell = cell_queue_pop(queue);
+ tor_assert(*next_circ_on_conn_p(circ,conn));
connection_or_write_cell_to_buf(cell, conn);
cell_free(cell);
++n_flushed;
+ if (circ != conn->active_circuits) {
+ /* If this happens, the current circuit just got made inactive by
+ * a call in connection_write_to_buf(). That's nothing to worry about:
+ * circuit_make_inactive_on_conn() already advanced conn->active_circuits
+ * for us.
+ */
+ assert_active_circuits_ok_paranoid(conn);
+ return n_flushed;
+ }
}
+ tor_assert(*next_circ_on_conn_p(circ,conn));
+ assert_active_circuits_ok_paranoid(conn);
conn->active_circuits = *next_circ_on_conn_p(circ, conn);
/* Is the cell queue low enough to unblock all the streams that are waiting