]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Prevent a potential three-thread deadlock. Also added a comment block
authorMark Michelson <mmichelson@digium.com>
Fri, 8 Feb 2008 18:48:17 +0000 (18:48 +0000)
committerMark Michelson <mmichelson@digium.com>
Fri, 8 Feb 2008 18:48:17 +0000 (18:48 +0000)
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/branches/1.4@103120 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_queue.c

index 3dbb7f0a4f53a31203af4a0e70d512969fa4950d..0374575eca69a2f7566c1a98699077a3ca268aff 100644 (file)
@@ -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);
                                }