Reference leaks in app_queue.

* Fixed load_realtime_queue() leaking a queue reference when it overwrites
q when processing a realtime queue.
(issue ASTERISK-18265)

* Make join_queue() unreference the queue returned by
load_realtime_queue() when it is done with the pointer.  The
load_realtime_queue() returns a reference to the just loaded realtime
queue.

* Fixed queues container reference leak in queues_data_provider_get().

* queue_unref() should not return q that was just unreferenced.

* Made logic in __queues_show() and queues_data_provider_get() when
calling load_realtime_queue() easier to understand.


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@332874 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Richard Mudgett
2011-08-22 19:32:19 +00:00
parent 56549c96ab
commit def9e8fe45

View File

@@ -1284,7 +1284,7 @@ static inline struct call_queue *queue_ref(struct call_queue *q)
static inline struct call_queue *queue_unref(struct call_queue *q)
{
ao2_ref(q, -1);
return q;
return NULL;
}
#endif
@@ -2324,6 +2324,7 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
return q;
}
/*! \note Returns a reference to the loaded realtime queue. */
static struct call_queue *load_realtime_queue(const char *queuename)
{
struct ast_variable *queue_vars;
@@ -2357,17 +2358,15 @@ static struct call_queue *load_realtime_queue(const char *queuename)
}
if (q) {
prev_weight = q->weight ? 1 : 0;
queue_t_unref(q, "Need to find realtime queue");
}
ao2_lock(queues);
q = find_queue_by_name_rt(queuename, queue_vars, member_config);
if (member_config) {
ast_config_destroy(member_config);
}
if (queue_vars) {
ast_variables_destroy(queue_vars);
}
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 */
if (q) {
if (!q->weight && prev_weight) {
@@ -2471,6 +2470,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
*reason = QUEUE_JOINEMPTY;
ao2_unlock(q);
ao2_unlock(queues);
queue_t_unref(q, "Done with realtime queue");
return res;
}
}
@@ -2534,6 +2534,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
}
ao2_unlock(q);
ao2_unlock(queues);
queue_t_unref(q, "Done with realtime queue");
return res;
}
@@ -6947,13 +6948,16 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
* queues which have been deleted from realtime but which have not yet
* been deleted from the in-core container
*/
if (q->realtime && !(realtime_queue = load_realtime_queue(q->name))) {
ao2_unlock(q);
queue_t_unref(q, "Done with iterator");
continue;
} else if (q->realtime) {
if (q->realtime) {
realtime_queue = load_realtime_queue(q->name);
if (!realtime_queue) {
ao2_unlock(q);
queue_t_unref(q, "Done with iterator");
continue;
}
queue_t_unref(realtime_queue, "Queue is already in memory");
}
if (argc == 3 && strcasecmp(q->name, argv[2])) {
ao2_unlock(q);
queue_t_unref(q, "Done with iterator");
@@ -8246,11 +8250,13 @@ static int queues_data_provider_get(const struct ast_data_search *search,
i = ao2_iterator_init(queues, 0);
while ((queue = ao2_iterator_next(&i))) {
ao2_lock(queue);
if (queue->realtime && !(queue_realtime = load_realtime_queue(queue->name))) {
ao2_unlock(queue);
queue_unref(queue);
continue;
} else if (queue->realtime) {
if (queue->realtime) {
queue_realtime = load_realtime_queue(queue->name);
if (!queue_realtime) {
ao2_unlock(queue);
queue_unref(queue);
continue;
}
queue_unref(queue_realtime);
}
@@ -8258,6 +8264,7 @@ static int queues_data_provider_get(const struct ast_data_search *search,
ao2_unlock(queue);
queue_unref(queue);
}
ao2_iterator_destroy(&i);
return 0;
}