From 9a78c1b7353a3adcd7e08ce4567bf5bc2962433c Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 15 Sep 2005 19:31:38 +0000 Subject: [PATCH] Fix deadlock when moving clients. Thanks to oddsock for producing a testcase and backtrace, and karl for fixing my brain svn path=/icecast/trunk/icecast/; revision=10017 --- src/source.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/source.c b/src/source.c index a0ab569e..cc10e9ba 100644 --- a/src/source.c +++ b/src/source.c @@ -340,7 +340,9 @@ void source_move_clients (source_t *source, source_t *dest) { client_t *client; - /* we need to move the client and pending trees */ + /* we need to move the client and pending trees - we must take the + * locks in this order to avoid deadlocks */ + avl_tree_wlock (source->client_tree); avl_tree_wlock (source->pending_tree); if (source->on_demand == 0 && source->format == NULL) @@ -381,7 +383,6 @@ void source_move_clients (source_t *source, source_t *dest) count++; } - avl_tree_wlock (source->client_tree); while (1) { avl_node *node = avl_get_first (source->client_tree); @@ -409,10 +410,12 @@ void source_move_clients (source_t *source, source_t *dest) source->listeners = 0; stats_event (source->mount, "listeners", "0"); - avl_tree_unlock (source->client_tree); } while (0); + avl_tree_unlock (source->pending_tree); + avl_tree_unlock (source->client_tree); + /* see if we need to wake up an on-demand relay */ if (dest->running == 0 && dest->on_demand && count) { @@ -420,7 +423,6 @@ void source_move_clients (source_t *source, source_t *dest) slave_rebuild_mounts(); } - avl_tree_unlock (source->pending_tree); avl_tree_unlock (dest->pending_tree); thread_mutex_unlock (&move_clients_mutex); }