diff options
author | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-02-08 18:48:17 +0000 |
---|---|---|
committer | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-02-08 18:48:17 +0000 |
commit | 8aded204cd453dff3bb6402bdecf2c2f76245c25 (patch) | |
tree | ee6e18e893ece13cb098853fe242c30c057a60e6 /apps | |
parent | 52bfc9d6f67aff332be439bfe6361b98e4e12cf5 (diff) |
Prevent a potential three-thread deadlock. Also added a comment block
to explicitly state the locking order necessary inside app_queue.
(closes issue #11862)
Reported by: flujan
Patches:
11862.patch uploaded by putnopvut (license 60)
Tested by: flujan
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@103120 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rw-r--r-- | apps/app_queue.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c index 3dbb7f0a4..0374575ec 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -99,6 +99,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/astobj2.h" #include "asterisk/global_datastores.h" +/* Please read before modifying this file. + * There are three locks which are regularly used + * throughout this file, the queue list lock, the lock + * for each individual queue, and the interface list lock. + * Please be extra careful to always lock in the following order + * 1) queue list lock + * 2) individual queue lock + * 3) interface list lock + * This order has sort of "evolved" over the lifetime of this + * application, but it is now in place this way, so please adhere + * to this order! + */ + + enum { QUEUE_STRATEGY_RINGALL = 0, QUEUE_STRATEGY_ROUNDROBIN, @@ -889,15 +903,16 @@ static int remove_from_interfaces(const char *interface) { struct member_interface *curint; + if (interface_exists_global(interface)) + return 0; + AST_LIST_LOCK(&interfaces); AST_LIST_TRAVERSE_SAFE_BEGIN(&interfaces, curint, list) { if (!strcasecmp(curint->interface, interface)) { - if (!interface_exists_global(interface)) { - if (option_debug) - ast_log(LOG_DEBUG, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface); - AST_LIST_REMOVE_CURRENT(&interfaces, list); - free(curint); - } + if (option_debug) + ast_log(LOG_DEBUG, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface); + AST_LIST_REMOVE_CURRENT(&interfaces, list); + free(curint); break; } } @@ -4248,9 +4263,9 @@ static int reload_queues(void) continue; } - remove_from_interfaces(cur->interface); q->membercount--; ao2_unlink(q->members, cur); + remove_from_interfaces(cur->interface); ao2_ref(cur, -1); } |