summaryrefslogtreecommitdiff
path: root/main/pbx.c
diff options
context:
space:
mode:
authorMatt Jordan <mjordan@digium.com>2015-04-19 15:49:43 -0500
committerMatt Jordan <mjordan@digium.com>2015-04-19 16:03:32 -0500
commit8e903b17ea7002bf5017589994c2acc06e0ada29 (patch)
tree146bf5042f6a9ed07ae3e39f78d32bfb0e4cb0a5 /main/pbx.c
parent8435a0cdff848f77ff55e709a393ea96635e5b19 (diff)
main/pbx: Don't attempt to destroy a previously destroyed exten/priority tuple
When a PBX registrar is unloaded, it will fail to remove its extension from the context root_table if a dialplan application used by that extension is still loaded. This can be the case for AGI, which can be unloaded after several of the standard PBX providers. Often, this is harmless; however, if the extension's priorities are removed during the failed unloading *and* the dialplan application later unregisters, it leaves a ticking timebomb for the next PBX provider that attempts to iterate over the extensions. When that occurs, the peer_table pointer on the extension will already be set to NULL. The current code does not check to see if the pointer is NULL before passing it to a hashtab function this is not NULL tolerant. Since it is possible for the peer_table to be NULL when we normally would not expect that to be the case, the solution in this patch is to simply skip over processing an extension's priorities if peer_table is NULL. Prior to this patch, the tests/pbx/callerid_match test would crash during module unload. With this patch, the test no longer crashes after running. ASTERISK-24774 #close Reported by: Corey Farrell Change-Id: I2bbeecb7e0f77bac303a1b9135e4cdb4db6d4c40
Diffstat (limited to 'main/pbx.c')
-rw-r--r--main/pbx.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/main/pbx.c b/main/pbx.c
index 209de66d1..fee4191aa 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -10735,6 +10735,16 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
exten_iter = ast_hashtab_start_traversal(tmp->root_table);
while ((exten_item=ast_hashtab_next(exten_iter))) {
int end_traversal = 1;
+
+ /*
+ * If the extension could not be removed from the root_table due to
+ * a loaded PBX app, it can exist here but have its peer_table be
+ * destroyed due to a previous pass through this function.
+ */
+ if (!exten_item->peer_table) {
+ continue;
+ }
+
prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
while ((prio_item=ast_hashtab_next(prio_iter))) {
char extension[AST_MAX_EXTENSION];