diff --git a/changes/bug18116 b/changes/bug18116 new file mode 100644 index 0000000000..23ff8f7775 --- /dev/null +++ b/changes/bug18116 @@ -0,0 +1,3 @@ + o Major bugfixes: + - Correctly handle detaching circuits from cmuxes when doing + circuit_free_all() on shutdown again; fixes bug #18116. diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index dcbeb1e2bb..9b7df75cd8 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -53,6 +53,7 @@ static void cpath_ref_decref(crypt_path_reference_t *cpath_ref); //static void circuit_set_rend_token(or_circuit_t *circ, int is_rend_circ, // const uint8_t *token); static void circuit_clear_rend_token(or_circuit_t *circ); +static void circuit_about_to_free_terminal(circuit_t *circ); static void circuit_about_to_free(circuit_t *circ); /********* END VARIABLES ************/ @@ -901,6 +902,7 @@ circuit_free_all(void) } } tmp->global_circuitlist_idx = -1; + circuit_about_to_free_terminal(tmp); circuit_free(tmp); SMARTLIST_DEL_CURRENT(lst, tmp); } SMARTLIST_FOREACH_END(tmp); @@ -1744,6 +1746,32 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line, smartlist_add(circuits_pending_close, circ); } +/** Called immediately before freeing a marked circuit circ from + * circuit_free_all() while shutting down Tor; this is a safe-at-shutdown + * version of circuit_about_to_free(). It's important that it at least + * do circuitmux_detach_circuit() when appropriate. + */ +static void +circuit_about_to_free_terminal(circuit_t *circ) +{ + + if (circ->n_chan) { + circuit_clear_cell_queue(circ, circ->n_chan); + circuitmux_detach_circuit(circ->n_chan->cmux, circ); + circuit_set_n_circid_chan(circ, 0, NULL); + } + + if (! CIRCUIT_IS_ORIGIN(circ)) { + or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); + + if (or_circ->p_chan) { + circuit_clear_cell_queue(circ, or_circ->p_chan); + circuitmux_detach_circuit(or_circ->p_chan->cmux, circ); + circuit_set_p_circid_chan(or_circ, 0, NULL); + } + } +} + /** Called immediately before freeing a marked circuit circ. * Disconnects the circuit from other data structures, launches events * as appropriate, and performs other housekeeping.