diff --git a/apps/app_queue.c b/apps/app_queue.c index 8b1072e..6e4730a 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -2359,6 +2359,7 @@ static struct call_queue *load_realtime_queue(const char *queuename) prev_weight = q->weight ? 1 : 0; } + ast_rdlock_contexts(); ao2_lock(queues); q = find_queue_by_name_rt(queuename, queue_vars, member_config); @@ -2379,6 +2380,7 @@ static struct call_queue *load_realtime_queue(const char *queuename) } /* Other cases will end up with the proper value for use_weight */ ao2_unlock(queues); + ast_unlock_contexts(); } else { update_realtime_members(q); @@ -2413,6 +2415,7 @@ static void update_realtime_members(struct call_queue *q) return; } + ast_rdlock_contexts(); ao2_lock(queues); ao2_lock(q); @@ -2447,6 +2450,7 @@ static void update_realtime_members(struct call_queue *q) ao2_iterator_destroy(&mem_iter); ao2_unlock(q); ao2_unlock(queues); + ast_unlock_contexts(); ast_config_destroy(member_config); } @@ -2461,6 +2465,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result * if (!(q = load_realtime_queue(queuename))) return res; + ast_rdlock_contexts(); ao2_lock(queues); ao2_lock(q); @@ -2471,6 +2476,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result * *reason = QUEUE_JOINEMPTY; ao2_unlock(q); ao2_unlock(queues); + ast_unlock_contexts(); return res; } } @@ -2524,6 +2530,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result * } ao2_unlock(q); ao2_unlock(queues); + ast_unlock_contexts(); return res; } @@ -4422,8 +4429,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce } /* Hold the lock while we setup the outgoing calls */ - if (need_weight) + if (need_weight) { + ast_rdlock_contexts(); ao2_lock(queues); + } ao2_lock(qe->parent); ast_debug(1, "%s is trying to call a queue member.\n", qe->chan->name); @@ -4442,8 +4451,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce ao2_ref(cur, -1); ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) + if (need_weight) { ao2_unlock(queues); + ast_unlock_contexts(); + } goto out; } if (!datastore) { @@ -4451,8 +4462,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce ao2_ref(cur, -1); ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) + if (need_weight) { ao2_unlock(queues); + ast_unlock_contexts(); + } callattempt_free(tmp); goto out; } @@ -4461,8 +4474,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce ao2_ref(cur, -1); ao2_unlock(&qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) + if (need_weight) { ao2_unlock(queues); + ast_unlock_contexts(); + } callattempt_free(tmp); goto out; } @@ -4499,8 +4514,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce ao2_ref(cur, -1); ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) + if (need_weight) { ao2_unlock(queues); + ast_unlock_contexts(); + } callattempt_free(tmp); goto out; } @@ -4563,8 +4580,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce ++qe->pending; ao2_unlock(qe->parent); ring_one(qe, outgoing, &numbusies); - if (need_weight) + if (need_weight) { ao2_unlock(queues); + ast_unlock_contexts(); + } lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, update_connectedline); /* The ast_channel_datastore_remove() function could fail here if the * datastore was moved to another channel during a masquerade. If this is @@ -5164,6 +5183,7 @@ static int remove_from_queue(const char *queuename, const char *interface) ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface)); if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) { + ast_rdlock_contexts(); ao2_lock(queues); ao2_lock(q); if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) { @@ -5173,6 +5193,7 @@ static int remove_from_queue(const char *queuename, const char *interface) ao2_unlock(q); queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference"); ao2_unlock(queues); + ast_unlock_contexts(); return RES_NOT_DYNAMIC; } q->membercount--; @@ -5193,6 +5214,7 @@ static int remove_from_queue(const char *queuename, const char *interface) } ao2_unlock(q); ao2_unlock(queues); + ast_unlock_contexts(); queue_t_unref(q, "Expiring temporary reference"); } @@ -5217,6 +5239,7 @@ static int add_to_queue(const char *queuename, const char *interface, const char if (!(q = load_realtime_queue(queuename))) return res; + ast_rdlock_contexts(); ao2_lock(queues); ao2_lock(q); @@ -5256,6 +5279,7 @@ static int add_to_queue(const char *queuename, const char *interface, const char } ao2_unlock(q); ao2_unlock(queues); + ast_unlock_contexts(); queue_t_unref(q, "Expiring temporary reference"); return res; @@ -5436,6 +5460,7 @@ static void reload_queue_members(void) struct call_queue *cur_queue; char queue_data[PM_MAX_LEN]; + ast_rdlock_contexts(); ao2_lock(queues); /* Each key in 'pm_family' is the name of a queue */ @@ -5509,6 +5534,7 @@ static void reload_queue_members(void) } ao2_unlock(queues); + ast_unlock_contexts(); if (db_tree) { ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n"); ast_db_freetree(db_tree); @@ -6785,6 +6811,7 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena } /* We've made it here, so it looks like we're doing operations on all queues. */ + ast_rdlock_contexts(); ao2_lock(queues); /* Mark all queues as dead for the moment if we're reloading queues. @@ -6811,6 +6838,7 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_queues, (char *) queuename); } ao2_unlock(queues); + ast_unlock_contexts(); return 0; } @@ -6919,6 +6947,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char * } queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK); + ast_rdlock_contexts(); ao2_lock(queues); while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { float sl; @@ -7004,6 +7033,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char * } ao2_iterator_destroy(&queue_iter); ao2_unlock(queues); + ast_unlock_contexts(); if (!found) { if (argc == 3) ast_str_set(&out, 0, "No such queue: %s.", argv[2]); diff --git a/main/pbx.c b/main/pbx.c index b9c8535..463bd18 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -4397,6 +4397,7 @@ static int handle_statechange(void *datap) /* Device state changed since last check - notify the watchers */ + ast_rdlock_contexts(); ao2_lock(hints); ao2_lock(hint); @@ -4405,6 +4406,7 @@ static int handle_statechange(void *datap) ao2_unlock(hint); ao2_t_ref(device, -1, "linked hint from device has no exten"); ao2_unlock(hints); + ast_unlock_contexts(); continue; } @@ -4426,6 +4428,7 @@ static int handle_statechange(void *datap) ao2_unlock(hint); ao2_t_ref(device, -1, "finished callbacks for device"); ao2_unlock(hints); + ast_unlock_contexts(); } if (iterator) { ao2_iterator_destroy(iterator); @@ -4447,6 +4450,7 @@ int ast_extension_state_add(const char *context, const char *exten, /* If there's no context and extension: add callback to statecbs list */ if (!context && !exten) { + ast_rdlock_contexts(); ao2_lock(hints); state_cb = ao2_find(statecbs, callback, 0); @@ -4454,12 +4458,14 @@ int ast_extension_state_add(const char *context, const char *exten, state_cb->data = data; ao2_ref(state_cb, -1); ao2_unlock(hints); + ast_unlock_contexts(); return 0; } /* Now insert the callback */ if (!(state_cb = ao2_alloc(sizeof(*state_cb), NULL))) { ao2_unlock(hints); + ast_unlock_contexts(); return -1; } state_cb->id = 0; @@ -4470,6 +4476,7 @@ int ast_extension_state_add(const char *context, const char *exten, ao2_ref(state_cb, -1); ao2_unlock(hints); + ast_unlock_contexts(); return 0; } @@ -4549,6 +4556,7 @@ int ast_extension_state_del(int id, ast_state_cb_type callback) } if (!id) { /* id == 0 is a callback without extension */ + ast_rdlock_contexts(); ao2_lock(hints); p_cur = ao2_find(statecbs, callback, OBJ_UNLINK); if (p_cur) { @@ -4556,6 +4564,7 @@ int ast_extension_state_del(int id, ast_state_cb_type callback) ao2_ref(p_cur, -1); } ao2_unlock(hints); + ast_unlock_contexts(); } else { /* callback with extension, find the callback based on ID */ struct ast_hint *hint;