From: Mark Michelson Date: Fri, 8 Feb 2008 18:54:53 +0000 (+0000) Subject: Merged revisions 103120 via svnmerge from X-Git-Tag: 1.6.0-beta3~2^2~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ba003e415b1f26cd3aee07365a3218658be94707;p=thirdparty%2Fasterisk.git Merged revisions 103120 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r103120 | mmichelson | 2008-02-08 12:48:17 -0600 (Fri, 08 Feb 2008) | 10 lines 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: https://origsvn.digium.com/svn/asterisk/trunk@103121 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/apps/app_queue.c b/apps/app_queue.c index 392c5a040c..cdb0d0791d 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -93,6 +93,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/strings.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_LEASTRECENT, @@ -1007,14 +1021,15 @@ 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)) { - ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface); - AST_LIST_REMOVE_CURRENT(list); - ast_free(curint); - } + ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface); + AST_LIST_REMOVE_CURRENT(&interfaces, list); + ast_free(curint); break; } }