diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-11-24 20:36:01 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-11-24 20:36:01 +0000 |
commit | 069bda98282a57ec0caf15c4f497a23c91028c2b (patch) | |
tree | 0f7d79abb724213267678ffc836708d7794fad4a /apps | |
parent | 031365419bf52340cdbec7faf900b144743e47d0 (diff) |
Merged revisions 231134 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
........
r231134 | tilghman | 2009-11-24 14:31:28 -0600 (Tue, 24 Nov 2009) | 7 lines
Found a few places where queue refcounts were counted incorrectly. Also add debug statements.
(closes issue #15982, closes issue #15984)
Reported by: atis
Patches:
20091111__issue15982.diff.txt uploaded by tilghman (license 14)
Tested by: atis
........
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@231136 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rw-r--r-- | apps/app_queue.c | 153 |
1 files changed, 85 insertions, 68 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c index 03490ead9..2eea2bf8b 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -95,6 +95,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/global_datastores.h" #include "asterisk/taskprocessor.h" +/* Define, to debug reference counts on queues, without debugging reference counts on queue members */ +/* #define REF_DEBUG_ONLY_QUEUES */ + /*! * \par Please read before modifying this file. * There are three locks which are regularly used @@ -870,6 +873,18 @@ static int queue_cmp_cb(void *obj, void *arg, int flags) return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0; } +#ifdef REF_DEBUG_ONLY_QUEUES +#define queue_ref(a) __ao2_ref_debug(a,1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__) +#define queue_unref(a) __ao2_ref_debug(a,-1,"",__FILE__,__LINE__,__PRETTY_FUNCTION__) +#define queue_t_ref(a,b) __ao2_ref_debug(a,1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__) +#define queue_t_unref(a,b) __ao2_ref_debug(a,-1,b,__FILE__,__LINE__,__PRETTY_FUNCTION__) +#define queues_t_link(c,q,tag) __ao2_link_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__) +#define queues_t_unlink(c,q,tag) __ao2_unlink_debug(c,q,tag,__FILE__,__LINE__,__PRETTY_FUNCTION__) +#else +#define queue_t_ref(a,b) queue_ref(a) +#define queue_t_unref(a,b) queue_unref(a) +#define queues_t_link(c,q,tag) ao2_t_link(c,q,tag) +#define queues_t_unlink(c,q,tag) ao2_t_unlink(c,q,tag) static inline struct call_queue *queue_ref(struct call_queue *q) { ao2_ref(q, 1); @@ -881,6 +896,7 @@ static inline struct call_queue *queue_unref(struct call_queue *q) ao2_ref(q, -1); return q; } +#endif /*! \brief Set variables of queue */ static void set_queue_variables(struct call_queue *q, struct ast_channel *chan) @@ -1032,7 +1048,7 @@ static int handle_statechange(void *datap) int found = 0; qiter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&qiter))) { + while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) { ao2_lock(q); miter = ao2_iterator_init(q->members, 0); @@ -1053,7 +1069,7 @@ static int handle_statechange(void *datap) ao2_iterator_destroy(&miter); ao2_unlock(q); - ao2_ref(q, -1); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&qiter); @@ -1647,9 +1663,9 @@ static struct call_queue *alloc_queue(const char *queuename) { struct call_queue *q; - if ((q = ao2_alloc(sizeof(*q), destroy_queue))) { + if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) { if (ast_string_field_init(q, 64)) { - ao2_ref(q, -1); + queue_t_unref(q, "String field allocation failed"); return NULL; } ast_string_field_set(q, name, queuename); @@ -1681,12 +1697,12 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as char tmpbuf[64]; /* Must be longer than the longest queue param name. */ /* Static queues override realtime. */ - if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) { + if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) { ao2_lock(q); if (!q->realtime) { if (q->dead) { ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Queue is dead; can't return it"); return NULL; } else { ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name); @@ -1694,7 +1710,6 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as return q; } } - queue_unref(q); } else if (!member_config) /* Not found in the list, and it's not realtime ... */ return NULL; @@ -1710,9 +1725,9 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as q->dead = 1; /* Delete if unused (else will be deleted when last caller leaves). */ - ao2_unlink(queues, q); + queues_t_unlink(queues, q, "Unused; removing from container"); ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Queue is dead; can't return it"); } return NULL; } @@ -1743,7 +1758,7 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as /* We traversed all variables and didn't find a strategy */ if (!tmpvar) q->strategy = QUEUE_STRATEGY_RINGALL; - ao2_link(queues, q); + queues_t_link(queues, q, "Add queue to container"); } init_queue(q); /* Ensure defaults for all parameters not set explicitly. */ @@ -1812,7 +1827,7 @@ static struct call_queue *load_realtime_queue(const char *queuename) int prev_weight = 0; /* Find the queue in the in-core list first. */ - q = ao2_find(queues, &tmpq, OBJ_POINTER); + q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first"); if (!q || q->realtime) { /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all @@ -2224,7 +2239,7 @@ static void leave_queue(struct queue_ent *qe) if (!(q = qe->parent)) return; - queue_ref(q); + queue_t_ref(q, "Copy queue pointer from queue entry"); ao2_lock(q); prev = NULL; @@ -2265,10 +2280,10 @@ static void leave_queue(struct queue_ent *qe) if (q->dead) { /* It's dead and nobody is in it, so kill it */ - ao2_unlink(queues, q); + queues_t_unlink(queues, q, "Queue is now dead; remove it from the container"); } /* unref the explicit ref earlier in the function */ - queue_unref(q); + queue_t_unref(q, "Expire copied reference"); } /*! \brief Hang up a list of outgoing calls */ @@ -2353,9 +2368,9 @@ static int compare_weight(struct call_queue *rq, struct member *member) /* 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_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { if (q == rq) { /* don't check myself, could deadlock */ - queue_unref(q); + queue_t_unref(q, "Done with iterator"); continue; } ao2_lock(q); @@ -2370,7 +2385,7 @@ static int compare_weight(struct call_queue *rq, struct member *member) } } ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); if (found) { break; } @@ -3251,7 +3266,7 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom if (shared_lastcall) { queue_iter = ao2_iterator_init(queues, 0); - while ((qtmp = ao2_iterator_next(&queue_iter))) { + while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { ao2_lock(qtmp); if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) { time(&mem->lastcall); @@ -3260,7 +3275,7 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom ao2_ref(mem, -1); } ao2_unlock(qtmp); - ao2_ref(qtmp, -1); + queue_t_unref(qtmp, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); } else { @@ -3508,7 +3523,7 @@ static void end_bridge_callback(void *data) set_queue_variables(q, chan); ao2_unlock(q); /* This unrefs the reference we made in try_calling when we allocated qeb */ - queue_unref(q); + queue_t_unref(q, "Expire bridge_config reference"); } } @@ -4241,7 +4256,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce * to make sure to increase the refcount of this queue so it cannot be freed until we * are done with it. We remove this reference in end_bridge_callback. */ - queue_ref(qe->parent); + queue_t_ref(qe->parent, "For bridge_config reference"); } time(&callstart); @@ -4384,7 +4399,7 @@ static int remove_from_queue(const char *queuename, const char *interface) int res = RES_NOSUCHQUEUE; ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface)); - if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) { + 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))) { @@ -4392,7 +4407,7 @@ static int remove_from_queue(const char *queuename, const char *interface) if (!mem->dynamic) { ao2_ref(mem, -1); ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference"); ao2_unlock(queues); return RES_NOT_DYNAMIC; } @@ -4414,7 +4429,7 @@ static int remove_from_queue(const char *queuename, const char *interface) } ao2_unlock(q); ao2_unlock(queues); - queue_unref(q); + queue_t_unref(q, "Expiring temporary reference"); } return res; @@ -4495,7 +4510,7 @@ static int set_member_paused(const char *queuename, const char *interface, const ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", ""); queue_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) { ao2_lock(q); if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) { if ((mem = interface_exists(q, interface))) { @@ -4512,6 +4527,7 @@ static int set_member_paused(const char *queuename, const char *interface, const ast_log(LOG_WARNING, "Failed %spausing realtime queue member %s:%s\n", (paused ? "" : "un"), q->name, interface); ao2_ref(mem, -1); ao2_unlock(q); + queue_t_unref(q, "Done with iterator"); continue; } found++; @@ -4544,12 +4560,12 @@ static int set_member_paused(const char *queuename, const char *interface, const if (!ast_strlen_zero(queuename) && !strcasecmp(queuename, q->name)) { ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); break; } ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); @@ -4570,7 +4586,7 @@ static int set_member_penalty(char *queuename, char *interface, int penalty) } queue_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { ao2_lock(q); if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) { foundqueue++; @@ -4588,7 +4604,7 @@ static int set_member_penalty(char *queuename, char *interface, int penalty) } } ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); @@ -4614,18 +4630,18 @@ static int get_member_penalty(char *queuename, char *interface) }; struct member *mem; - if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) { + if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Search for queue"))) { foundqueue = 1; ao2_lock(q); if ((mem = interface_exists(q, interface))) { penalty = mem->penalty; ao2_ref(mem, -1); ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Search complete"); return penalty; } ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Search complete"); } /* some useful debuging */ @@ -4667,7 +4683,7 @@ static void reload_queue_members(void) struct call_queue tmpq = { .name = queue_name, }; - cur_queue = ao2_find(queues, &tmpq, OBJ_POINTER); + cur_queue = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Reload queue members"); } if (!cur_queue) @@ -4682,7 +4698,7 @@ static void reload_queue_members(void) } if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN)) { - queue_unref(cur_queue); + queue_t_unref(cur_queue, "Expire reload reference"); continue; } @@ -4724,7 +4740,7 @@ static void reload_queue_members(void) break; } } - queue_unref(cur_queue); + queue_t_unref(cur_queue, "Expire reload reference"); } ao2_unlock(queues); @@ -5297,7 +5313,7 @@ static int queue_function_var(struct ast_channel *chan, const char *cmd, char *d return -1; } - if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) { + if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE() function"))) { ao2_lock(q); if (q->setqueuevar) { sl = 0; @@ -5315,7 +5331,7 @@ static int queue_function_var(struct ast_channel *chan, const char *cmd, char *d } ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with QUEUE() function"); } else { ast_log(LOG_WARNING, "queue %s was not found\n", data); } @@ -5372,7 +5388,7 @@ static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *d } else /* must be "count" */ count = q->membercount; ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()"); } else ast_log(LOG_WARNING, "queue %s was not found\n", data); @@ -5416,7 +5432,7 @@ static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, cha } ao2_iterator_destroy(&mem_iter); ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER_COUNT"); } else ast_log(LOG_WARNING, "queue %s was not found\n", data); @@ -5441,11 +5457,11 @@ static int queue_function_queuewaitingcount(struct ast_channel *chan, const char return -1; } - if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) { + if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_WAITING_COUNT()"))) { ao2_lock(q); count = q->count; ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with reference in QUEUE_WAITING_COUNT()"); } else if ((var = ast_load_realtime("queues", "name", data, SENTINEL))) { /* if the queue is realtime but was not found in memory, this * means that the queue had been deleted from memory since it was @@ -5477,7 +5493,7 @@ static int queue_function_queuememberlist(struct ast_channel *chan, const char * return -1; } - if ((q = ao2_find(queues, &tmpq, OBJ_POINTER))) { + if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_MEMBER_LIST()"))) { int buflen = 0, count = 0; struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0); @@ -5500,7 +5516,7 @@ static int queue_function_queuememberlist(struct ast_channel *chan, const char * } ao2_iterator_destroy(&mem_iter); ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with QUEUE_MEMBER_LIST()"); } else ast_log(LOG_WARNING, "queue %s was not found\n", data); @@ -5812,7 +5828,7 @@ static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER); int prev_weight = 0; struct ast_variable *var; - if (!(q = ao2_find(queues, &tmpq, OBJ_POINTER))) { + if (!(q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find queue for reload"))) { if (queue_reload) { /* Make one then */ if (!(q = alloc_queue(queuename))) { @@ -5840,7 +5856,7 @@ static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, /* It should be impossible to *not* hit this case*/ ao2_unlock(q); } - queue_unref(q); + queue_t_unref(q, "We exist! Expiring temporary pointer"); return; } /* Due to the fact that the "linear" strategy will have a different allocation @@ -5888,11 +5904,11 @@ static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, } if (new) { - ao2_link(queues, q); + queues_t_link(queues, q, "Add queue to container"); } else { ao2_unlock(q); } - queue_unref(q); + queue_t_unref(q, "Expiring creation reference"); } static int mark_dead_and_unfound(void *obj, void *arg, int flags) @@ -5993,11 +6009,12 @@ static int clear_stats(const char *queuename) { struct call_queue *q; struct ao2_iterator queue_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { ao2_lock(q); if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) clear_queue(q); ao2_unlock(q); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); return 0; @@ -6061,7 +6078,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) if (argc == 3) { /* specific queue */ if ((q = load_realtime_queue(argv[2]))) { - queue_unref(q); + queue_t_unref(q, "Done with temporary pointer"); } } else if (ast_check_realtime("queues")) { /* This block is to find any queues which are defined in realtime but @@ -6072,7 +6089,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) if (cfg) { for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) { if ((q = load_realtime_queue(queuename))) { - queue_unref(q); + queue_t_unref(q, "Done with temporary pointer"); } } ast_config_destroy(cfg); @@ -6081,7 +6098,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK); ao2_lock(queues); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { float sl; struct call_queue *realtime_queue = NULL; @@ -6092,14 +6109,14 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) */ if (q->realtime && !(realtime_queue = load_realtime_queue(q->name))) { ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); continue; } else if (q->realtime) { - queue_unref(realtime_queue); + queue_t_unref(realtime_queue, "Queue is already in memory"); } if (argc == 3 && strcasecmp(q->name, argv[2])) { ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); continue; } found = 1; @@ -6161,7 +6178,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) } do_print(s, fd, ""); /* blank line between entries */ ao2_unlock(q); - queue_unref(q); /* Unref the iterator's reference */ + queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */ } ao2_iterator_destroy(&queue_iter); ao2_unlock(queues); @@ -6184,13 +6201,13 @@ static char *complete_queue(const char *line, const char *word, int pos, int sta struct ao2_iterator queue_iter; queue_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { if (!strncasecmp(word, q->name, wordlen) && ++which > state) { ret = ast_strdup(q->name); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); break; } - queue_unref(q); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); @@ -6279,7 +6296,7 @@ static int manager_queues_summary(struct mansession *s, const struct message *m) if (!ast_strlen_zero(id)) snprintf(idText, 256, "ActionID: %s\r\n", id); queue_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { ao2_lock(q); /* List queue properties */ @@ -6321,7 +6338,7 @@ static int manager_queues_summary(struct mansession *s, const struct message *m) q->name, qmemcount, qmemavail, qchancount, q->holdtime, q->talktime, qlongestholdtime, idText); } ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); astman_append(s, @@ -6354,7 +6371,7 @@ static int manager_queues_status(struct mansession *s, const struct message *m) snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); queue_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { ao2_lock(q); /* List queue properties */ @@ -6418,7 +6435,7 @@ static int manager_queues_status(struct mansession *s, const struct message *m) } } ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); @@ -6757,7 +6774,7 @@ static char *complete_queue_remove_member(const char *line, const char *word, in /* here is the case for 3, <member> */ queue_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&queue_iter))) { + while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { ao2_lock(q); mem_iter = ao2_iterator_init(q->members, 0); while ((m = ao2_iterator_next(&mem_iter))) { @@ -6766,7 +6783,7 @@ static char *complete_queue_remove_member(const char *line, const char *word, in ao2_unlock(q); tmp = ast_strdup(m->interface); ao2_ref(m, -1); - queue_unref(q); + queue_t_unref(q, "Done with iterator, returning interface name"); ao2_iterator_destroy(&mem_iter); ao2_iterator_destroy(&queue_iter); return tmp; @@ -6775,7 +6792,7 @@ static char *complete_queue_remove_member(const char *line, const char *word, in } ao2_iterator_destroy(&mem_iter); ao2_unlock(q); - queue_unref(q); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&queue_iter); @@ -7173,9 +7190,9 @@ static int unload_module(void) } q_iter = ao2_iterator_init(queues, 0); - while ((q = ao2_iterator_next(&q_iter))) { - ao2_unlink(queues, q); - queue_unref(q); + while ((q = ao2_t_iterator_next(&q_iter, "Iterate through queues"))) { + queues_t_unlink(queues, q, "Remove queue from container due to unload"); + queue_t_unref(q, "Done with iterator"); } ao2_iterator_destroy(&q_iter); ao2_ref(queues, -1); |