(closes issue #12689)
authorSteve Murphy <murf@digium.com>
Mon, 16 Jun 2008 20:43:46 +0000 (20:43 +0000)
committerSteve Murphy <murf@digium.com>
Mon, 16 Jun 2008 20:43:46 +0000 (20:43 +0000)
Reported by: ys

Many thanks to ys for doing the research on this problem.
I didn't think it would be best to unlock the contexts
and then relock them after the remove_extension2() call,
so I added an extra arg to remove_extension2() and set it
appropriately in each call. There were not that many.

I considered forcing the code to lock the contexts before
the call to remove_extension2(), but that would require
a slightly greater degree of changes, especially since
the find_context_locked is local to pbx.c

I did a simple sanity test to make sure the code doesn't
mess things up in general.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@123165 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_dial.c
apps/app_queue.c
apps/app_stack.c
include/asterisk/pbx.h
main/features.c
main/pbx.c

index 490fa34..abd6b47 100644 (file)
@@ -2098,7 +2098,7 @@ static int unload_module(void)
        res |= ast_unregister_application(rapp);
 
        if ((con = ast_context_find("app_dial_gosub_virtual_context"))) {
-               ast_context_remove_extension2(con, "s", 1, NULL);
+               ast_context_remove_extension2(con, "s", 1, NULL, 0);
                ast_context_destroy(con, "app_dial"); /* leave nothing behind */
        }
 
index 5e7289a..6d40c39 100644 (file)
@@ -6366,7 +6366,7 @@ static int unload_module(void)
                ast_event_unsubscribe(device_state_sub);
 
        if ((con = ast_context_find("app_queue_gosub_virtual_context"))) {
-               ast_context_remove_extension2(con, "s", 1, NULL);
+               ast_context_remove_extension2(con, "s", 1, NULL, 0);
                ast_context_destroy(con, "app_queue"); /* leave no trace */
        }
 
index 562be8a..669f7f4 100644 (file)
@@ -496,7 +496,7 @@ static int unload_module(void)
                ast_agi_unregister(ast_module_info->self, &gosub_agi_command);
 
                if ((con = ast_context_find("app_stack_gosub_virtual_context"))) {
-                       ast_context_remove_extension2(con, "s", 1, NULL);
+                       ast_context_remove_extension2(con, "s", 1, NULL, 0);
                        ast_context_destroy(con, "app_stack"); /* leave nothing behind */
                }
        }
index 3e3669a..87a594c 100644 (file)
@@ -600,7 +600,7 @@ int ast_context_remove_extension(const char *context, const char *extension, int
        const char *registrar);
 
 int ast_context_remove_extension2(struct ast_context *con, const char *extension,
-       int priority, const char *registrar);
+       int priority, const char *registrar, int already_locked);
 
 /*! 
  * \brief Add an ignorepat
index 06b0a3c..ccd182d 100644 (file)
@@ -2465,7 +2465,7 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
                        /* And take them out of the parking lot */
                        con = ast_context_find(pu->parkinglot->parking_con);
                        if (con) {
-                               if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
+                               if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
                                        ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
                                else
                                        notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
@@ -2500,7 +2500,7 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
                                        /* And take them out of the parking lot */
                                        con = ast_context_find(curlot->parking_con);
                                        if (con) {
-                                               if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
+                                               if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
                                                        ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
                                                else
                                                        notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
@@ -2721,7 +2721,7 @@ static int park_exec_full(struct ast_channel *chan, void *data, struct ast_parki
                peer = pu->chan;
                con = ast_context_find(parkinglot->parking_con);
                if (con) {
-                       if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
+                       if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
                                ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
                        else
                                notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
@@ -3284,7 +3284,7 @@ static int load_config(void)
 
        /* Remove the old parking extension */
        if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))     {
-               if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
+               if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar, 0))
                                notify_metermaids(old_parking_ext, old_parking_con, AST_DEVICE_NOT_INUSE);
                ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
        }
index 6bb8a14..9654bd8 100644 (file)
@@ -4022,7 +4022,7 @@ int ast_context_remove_extension(const char *context, const char *extension, int
        struct ast_context *c = find_context_locked(context);
 
        if (c) { /* ... remove extension ... */
-               ret = ast_context_remove_extension2(c, extension, priority, registrar);
+               ret = ast_context_remove_extension2(c, extension, priority, registrar, 1);
                ast_unlock_contexts();
        }
        return ret;
@@ -4038,14 +4038,15 @@ int ast_context_remove_extension(const char *context, const char *extension, int
  * it.
  *
  */
-int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
+int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 {
        struct ast_exten *exten, *prev_exten = NULL;
        struct ast_exten *peer;
        struct ast_exten ex, *exten2, *exten3;
        char dummy_name[1024];
 
-       ast_wrlock_context(con);
+       if (!already_locked)
+               ast_wrlock_context(con);
 
        /* Handle this is in the new world */
 
@@ -4132,7 +4133,8 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
        }
        if (!exten) {
                /* we can't find right extension */
-               ast_unlock_context(con);
+               if (!already_locked)
+                       ast_unlock_context(con);
                return -1;
        }
 
@@ -4159,7 +4161,8 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
                                break; /* found our priority */
                }
                if (!peer) { /* not found */
-                       ast_unlock_context(con);
+                       if (!already_locked)
+                               ast_unlock_context(con);
                        return -1;
                }
                /* we are first priority extension? */
@@ -4192,7 +4195,8 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
                destroy_exten(peer);
                /* XXX should we return -1 ? */
        }
-       ast_unlock_context(con);
+       if (!already_locked)
+               ast_unlock_context(con);
        return 0;
 }
 
@@ -7177,7 +7181,7 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
                                                ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
                                                                tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
                                                
-                                               ast_context_remove_extension2(tmp, prio_item->exten, prio_item->priority, registrar);
+                                               ast_context_remove_extension2(tmp, prio_item->exten, prio_item->priority, registrar, 1);
                                        }
                                        ast_hashtab_end_traversal(prio_iter);
                                }