diff --git a/apps/app_queue.c b/apps/app_queue.c index 07b8d7db48..7d8493a4cd 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -2418,13 +2418,11 @@ static struct call_queue *load_realtime_queue(const char *queuename) queue_t_unref(q, "Need to find realtime queue"); } - ao2_lock(queues); - q = find_queue_by_name_rt(queuename, queue_vars, member_config); ast_config_destroy(member_config); ast_variables_destroy(queue_vars); - /* update the use_weight value if the queue's has gained or lost a weight */ + /* update the use_weight value if the queue's has gained or lost a weight */ if (q) { if (!q->weight && prev_weight) { ast_atomic_fetchadd_int(&use_weight, -1); @@ -2434,8 +2432,6 @@ 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); - } else { update_realtime_members(q); } @@ -2469,10 +2465,9 @@ static void update_realtime_members(struct call_queue *q) return; } - ao2_lock(queues); ao2_lock(q); - - /* Temporarily set realtime members dead so we can detect deleted ones.*/ + + /* Temporarily set realtime members dead so we can detect deleted ones.*/ mem_iter = ao2_iterator_init(q->members, 0); while ((m = ao2_iterator_next(&mem_iter))) { if (m->realtime) @@ -2501,7 +2496,6 @@ static void update_realtime_members(struct call_queue *q) } ao2_iterator_destroy(&mem_iter); ao2_unlock(q); - ao2_unlock(queues); ast_config_destroy(member_config); } @@ -2516,7 +2510,6 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result * if (!(q = load_realtime_queue(queuename))) return res; - ao2_lock(queues); ao2_lock(q); /* This is our one */ @@ -2525,7 +2518,6 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result * if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty))) { *reason = QUEUE_JOINEMPTY; ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Done with realtime queue"); return res; } @@ -2589,7 +2581,6 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result * ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos ); } ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Done with realtime queue"); return res; @@ -2982,9 +2973,7 @@ static int compare_weight(struct call_queue *rq, struct member *member) struct member *mem; int found = 0; struct ao2_iterator queue_iter; - - /* q's lock and rq's lock already set by try_calling() - * to solve deadlock */ + queue_iter = ao2_iterator_init(queues, 0); while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { if (q == rq) { /* don't check myself, could deadlock */ @@ -4448,7 +4437,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce struct ao2_iterator memi; struct ast_datastore *datastore, *transfer_ds; struct queue_end_bridge *queue_end_bridge = NULL; - const int need_weight = use_weight; ast_channel_lock(qe->chan); datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL); @@ -4531,9 +4519,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce qe->cancel_answered_elsewhere = 1; } - /* Hold the lock while we setup the outgoing calls */ - if (need_weight) - ao2_lock(queues); ao2_lock(qe->parent); ast_debug(1, "%s is trying to call a queue member.\n", qe->chan->name); @@ -4552,8 +4537,6 @@ 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) - ao2_unlock(queues); goto out; } if (!datastore) { @@ -4561,8 +4544,6 @@ 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) - ao2_unlock(queues); callattempt_free(tmp); goto out; } @@ -4571,8 +4552,6 @@ 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) - ao2_unlock(queues); callattempt_free(tmp); goto out; } @@ -4609,8 +4588,6 @@ 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) - ao2_unlock(queues); callattempt_free(tmp); goto out; } @@ -4673,8 +4650,6 @@ 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) - ao2_unlock(queues); 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 @@ -5279,7 +5254,6 @@ 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"))) { - ao2_lock(queues); ao2_lock(q); if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) { /* XXX future changes should beware of this assumption!! */ @@ -5290,7 +5264,6 @@ static int remove_from_queue(const char *queuename, const char *interface) ao2_ref(mem, -1); ao2_unlock(q); queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference"); - ao2_unlock(queues); return RES_NOT_DYNAMIC; } q->membercount--; @@ -5310,7 +5283,6 @@ static int remove_from_queue(const char *queuename, const char *interface) res = RES_EXISTS; } ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Expiring temporary reference"); } @@ -5335,8 +5307,6 @@ static int add_to_queue(const char *queuename, const char *interface, const char if (!(q = load_realtime_queue(queuename))) return res; - ao2_lock(queues); - ao2_lock(q); if ((old_member = interface_exists(q, interface)) == NULL) { if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface))) { @@ -5374,7 +5344,6 @@ static int add_to_queue(const char *queuename, const char *interface, const char res = RES_EXISTS; } ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Expiring temporary reference"); return res; @@ -5554,8 +5523,6 @@ static void reload_queue_members(void) struct call_queue *cur_queue; char queue_data[PM_MAX_LEN]; - ao2_lock(queues); - /* Each key in 'pm_family' is the name of a queue */ db_tree = ast_db_gettree(pm_family, NULL); for (entry = db_tree; entry; entry = entry->next) { @@ -5626,7 +5593,6 @@ static void reload_queue_members(void) queue_t_unref(cur_queue, "Expire reload reference"); } - ao2_unlock(queues); if (db_tree) { ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n"); ast_db_freetree(db_tree); @@ -7012,14 +6978,11 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena return -1; } - /* We've made it here, so it looks like we're doing operations on all queues. */ - ao2_lock(queues); - /* Mark all queues as dead for the moment if we're reloading queues. * For clarity, we could just be reloading members, in which case we don't want to mess * with the other queue parameters at all*/ if (queue_reload) { - ao2_callback(queues, OBJ_NODATA, mark_dead_and_unfound, (char *) queuename); + ao2_callback(queues, OBJ_NODATA | OBJ_NOLOCK, mark_dead_and_unfound, (char *) queuename); } /* Chug through config file */ @@ -7036,17 +6999,16 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena ast_config_destroy(cfg); /* Unref all the dead queues if we were reloading queues */ if (queue_reload) { - ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_queues, (char *) queuename); + ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NOLOCK, kill_dead_queues, (char *) queuename); } - ao2_unlock(queues); return 0; } - + /*! \brief Facilitates resetting statistics for a queue * * This function actually does not reset any statistics, but * rather finds a call_queue struct which corresponds to the - * passed-in queue name and passes that structure to the + * passed-in queue name and passes that structure to the * clear_queue function. If no queuename is passed in, then * all queues will have their statistics reset. *