aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2023-10-11 10:51:16 -0400
committerMike Perry <mikeperry-git@torproject.org>2023-10-16 21:18:57 +0000
commita382337be629ff74e621d2e24c8048e9e8d31d26 (patch)
treee5e2df17dcab41d148ec20126721fcbdc0c7725c /src/core
parentc11ba9dea8aea6f502e7041b6376983cf295666f (diff)
downloadtor-a382337be629ff74e621d2e24c8048e9e8d31d26.tar.gz
tor-a382337be629ff74e621d2e24c8048e9e8d31d26.zip
conflux: Flag set as in full teardown in the free path
We suspect a shutdown race of some sort for which the full teardown is not noticed during the close but should be during the free. For that, we flag the conflux set as in full teardown (if so) in the free path in case the close path didn't caught it. Fixes #40870 Signed-off-by: David Goulet <dgoulet@torproject.org>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/or/conflux_pool.c43
-rw-r--r--src/core/or/conflux_pool.h2
2 files changed, 42 insertions, 3 deletions
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
index 4a7e941372..ec2938aefc 100644
--- a/src/core/or/conflux_pool.c
+++ b/src/core/or/conflux_pool.c
@@ -1607,7 +1607,22 @@ linked_circuit_free(circuit_t *circ, bool is_client)
/* Circuit can be freed without being closed and so we try to delete this leg
* so we can learn if this circuit is the last leg or not. */
- cfx_del_leg(circ->conflux, circ);
+ if (cfx_del_leg(circ->conflux, circ)) {
+ /* Check for instances of bug #40870, which we suspect happen
+ * during exit. If any happen outside of exit, BUG and warn. */
+ if (!circ->conflux->in_full_teardown) {
+ /* We should bug and warn if we're not in a shutdown process; that
+ * means we got here somehow without a close. */
+ if (BUG(!shutting_down)) {
+ log_warn(LD_BUG,
+ "Conflux circuit %p being freed without being marked for "
+ "full teardown via close, with shutdown state %d. "
+ "Please report this.", circ, shutting_down);
+ conflux_log_set(LOG_WARN, circ->conflux, is_client);
+ }
+ circ->conflux->in_full_teardown = true;
+ }
+ }
if (CONFLUX_NUM_LEGS(circ->conflux) > 0) {
/* The last leg will free the streams but until then, we nullify to avoid
@@ -2126,14 +2141,36 @@ conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client)
}
}
+/**
+ * Conflux needs a notification when tor_shutdown() begins, so that
+ * when circuits are freed, new legs are not launched.
+ *
+ * This needs a separate notification from conflux_pool_free_all(),
+ * because circuits must be freed before that function.
+ */
+void
+conflux_notify_shutdown(void)
+{
+ shutting_down = true;
+}
+
+#ifdef TOR_UNIT_TESTS
+/**
+ * For unit tests: Clear the shutting down state so we resume building legs.
+ */
+void
+conflux_clear_shutdown(void)
+{
+ shutting_down = false;
+}
+#endif
+
/** Free and clean up the conflux pool subsystem. This is called by the subsys
* manager AFTER all circuits have been freed which implies that all objects in
* the pools aren't referenced anymore. */
void
conflux_pool_free_all(void)
{
- shutting_down = true;
-
digest256map_free(client_linked_pool, free_conflux_void_);
digest256map_free(server_linked_pool, free_conflux_void_);
digest256map_free(client_unlinked_pool, free_unlinked_void_);
diff --git a/src/core/or/conflux_pool.h b/src/core/or/conflux_pool.h
index afa4d9d058..eba726b03a 100644
--- a/src/core/or/conflux_pool.h
+++ b/src/core/or/conflux_pool.h
@@ -12,6 +12,7 @@
#include "core/or/or.h"
void conflux_pool_init(void);
+void conflux_notify_shutdown(void);
void conflux_pool_free_all(void);
origin_circuit_t *conflux_get_circ_for_conn(const entry_connection_t *conn,
@@ -41,6 +42,7 @@ void conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client);
#ifdef TOR_UNIT_TESTS
bool launch_new_set(int num_legs);
+void conflux_clear_shutdown(void);
digest256map_t *get_linked_pool(bool is_client);
digest256map_t *get_unlinked_pool(bool is_client);
extern uint8_t DEFAULT_CLIENT_UX;