From d49fd42eecee6c7cff7b3d804b2e52eb44f53e10 Mon Sep 17 00:00:00 2001 From: Karl Heyes Date: Sun, 11 Jan 2009 16:46:08 +0000 Subject: [PATCH] lock order updates. hard to trigger case in source fallback. The other changes are for consistency. svn path=/icecast/trunk/icecast/; revision=15619 --- src/admin.c | 3 +++ src/cfgfile.c | 2 -- src/connection.c | 9 ++++++--- src/source.c | 25 ++++++++++++++----------- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/admin.c b/src/admin.c index efcb4e66..8a425d5e 100644 --- a/src/admin.c +++ b/src/admin.c @@ -344,9 +344,11 @@ void admin_handle_request(client_t *client, const char *uri) client_send_400 (client, "missing pass parameter"); return; } + global_lock(); config = config_get_config (); sc_mount = config->shoutcast_mount; listener = config_get_listen_sock (config, client->con); + if (listener && listener->shoutcast_mount) sc_mount = listener->shoutcast_mount; @@ -354,6 +356,7 @@ void admin_handle_request(client_t *client, const char *uri) httpp_setvar (client->parser, HTTPP_VAR_PROTOCOL, "ICY"); httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, pass); config_release_config (); + global_unlock(); } mount = httpp_get_query_param(client->parser, "mount"); diff --git a/src/cfgfile.c b/src/cfgfile.c index 5eac93d0..0f552c71 100644 --- a/src/cfgfile.c +++ b/src/cfgfile.c @@ -1136,7 +1136,6 @@ listener_t *config_get_listen_sock (ice_config_t *config, connection_t *con) int i = 0; listener = config->listen_sock; - global_lock(); while (listener) { if (i >= global.server_sockets) @@ -1149,7 +1148,6 @@ listener_t *config_get_listen_sock (ice_config_t *config, connection_t *con) i++; } } - global_unlock(); return listener; } diff --git a/src/connection.c b/src/connection.c index b660938e..740614c6 100644 --- a/src/connection.c +++ b/src/connection.c @@ -718,13 +718,13 @@ void connection_accept_loop (void) thread_sleep (400000); continue; } - global_unlock(); /* setup client for reading incoming http */ client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000'; if (sock_set_blocking (client->con->sock, 0) || sock_set_nodelay (client->con->sock)) { + global_unlock(); WARN0 ("failed to set tcp options on client connection, dropping"); client_destroy (client); continue; @@ -733,6 +733,7 @@ void connection_accept_loop (void) node = calloc (1, sizeof (client_queue_t)); if (node == NULL) { + global_unlock(); client_destroy (client); continue; } @@ -750,6 +751,7 @@ void connection_accept_loop (void) if (listener->shoutcast_mount) node->shoutcast_mount = strdup (listener->shoutcast_mount); } + global_unlock(); config_release_config(); _add_request_queue (node); @@ -778,11 +780,12 @@ void connection_accept_loop (void) */ int connection_complete_source (source_t *source, int response) { - ice_config_t *config = config_get_config(); + ice_config_t *config; global_lock (); DEBUG1 ("sources count is %d", global.sources); + config = config_get_config(); if (global.sources < config->source_limit) { const char *contenttype; @@ -797,8 +800,8 @@ int connection_complete_source (source_t *source, int response) if (format_type == FORMAT_ERROR) { - global_unlock(); config_release_config(); + global_unlock(); if (response) { client_send_403 (source->client, "Content-type not supported"); diff --git a/src/source.c b/src/source.c index 26b228cd..d6867749 100644 --- a/src/source.c +++ b/src/source.c @@ -195,7 +195,7 @@ void source_clear_source (source_t *source) { DEBUG1 ("clearing source \"%s\"", source->mount); - avl_tree_wlock (source->client_tree); + avl_tree_wlock (source->pending_tree); client_destroy(source->client); source->client = NULL; source->parser = NULL; @@ -216,19 +216,19 @@ void source_clear_source (source_t *source) stats_event_sub (NULL, "listeners", source->listeners); /* lets kick off any clients that are left on here */ + avl_tree_wlock (source->client_tree); while (avl_get_first (source->client_tree)) { avl_delete (source->client_tree, avl_get_first (source->client_tree)->key, _free_client); } + avl_tree_unlock (source->client_tree); - avl_tree_wlock (source->pending_tree); while (avl_get_first (source->pending_tree)) { avl_delete (source->pending_tree, avl_get_first(source->pending_tree)->key, _free_client); } - avl_tree_unlock (source->pending_tree); if (source->format && source->format->free_plugin) source->format->free_plugin (source->format); @@ -274,7 +274,7 @@ void source_clear_source (source_t *source) } source->on_demand_req = 0; - avl_tree_unlock (source->client_tree); + avl_tree_unlock (source->pending_tree); } @@ -338,22 +338,23 @@ void source_move_clients (source_t *source, source_t *dest) /* if the destination is not running then we can't move clients */ + avl_tree_wlock (dest->pending_tree); if (dest->running == 0 && dest->on_demand == 0) { WARN1 ("destination mount %s not running, unable to move clients ", dest->mount); + avl_tree_unlock (dest->pending_tree); thread_mutex_unlock (&move_clients_mutex); return; } - avl_tree_wlock (dest->pending_tree); do { client_t *client; /* 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); + avl_tree_wlock (source->client_tree); if (source->on_demand == 0 && source->format == NULL) { @@ -707,6 +708,9 @@ void source_main (source_t *source) if (source->queue_size > source->queue_size_limit) remove_from_q = 1; + /* acquire write lock on pending_tree */ + avl_tree_wlock(source->pending_tree); + /* acquire write lock on client_tree */ avl_tree_wlock(source->client_tree); @@ -727,9 +731,6 @@ void source_main (source_t *source) client_node = avl_get_next(client_node); } - /* acquire write lock on pending_tree */ - avl_tree_wlock(source->pending_tree); - /** add pending clients **/ client_node = avl_get_first(source->pending_tree); while (client_node) { @@ -1365,10 +1366,12 @@ static void *source_fallback_file (void *arg) */ void source_recheck_mounts (int update_all) { - ice_config_t *config = config_get_config(); - mount_proxy *mount = config->mounts; + ice_config_t *config; + mount_proxy *mount; avl_tree_rlock (global.source_tree); + config = config_get_config(); + mount = config->mounts; if (update_all) stats_clear_virtual_mounts (); -- GitLab