diff options
author | Richard Mudgett <rmudgett@digium.com> | 2012-01-27 18:47:16 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2012-01-27 18:47:16 +0000 |
commit | 27b69e7d29dc100e5fdf3cf911c3a02f3b5fd2b5 (patch) | |
tree | 7ad1cbac33a65eb9773db40058cabff69fe2eef1 | |
parent | 5bfea5fdbfca835b29e14ec9a28345c6095431b5 (diff) |
Audit of ao2_iterator_init() usage for v1.8.
Fixes numerous reference leaks and missing ao2_iterator_destroy() calls as
a result.
Review: https://reviewboard.asterisk.org/r/1697/
........
Merged revisions 352955 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 352956 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@352957 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | apps/app_chanspy.c | 13 | ||||
-rw-r--r-- | apps/app_queue.c | 31 | ||||
-rw-r--r-- | channels/chan_iax2.c | 16 | ||||
-rw-r--r-- | channels/chan_sip.c | 10 | ||||
-rw-r--r-- | include/asterisk/indications.h | 3 | ||||
-rw-r--r-- | main/indications.c | 2 | ||||
-rw-r--r-- | main/pbx.c | 1 | ||||
-rw-r--r-- | main/taskprocessor.c | 2 | ||||
-rw-r--r-- | res/res_odbc.c | 5 | ||||
-rw-r--r-- | res/res_srtp.c | 46 | ||||
-rw-r--r-- | res/snmp/agent.c | 9 |
11 files changed, 86 insertions, 52 deletions
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 54e473681..4c709cfcc 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -828,11 +828,13 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags, } if (!iter) { - return -1; + res = -1; + goto exit; } res = ast_waitfordigit(chan, waitms); if (res < 0) { + iter = ast_channel_iterator_destroy(iter); ast_clear_flag(chan, AST_FLAG_SPYING); break; } @@ -840,10 +842,12 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags, char tmp[2]; tmp[0] = res; tmp[1] = '\0'; - if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) + if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) { + iter = ast_channel_iterator_destroy(iter); goto exit; - else + } else { ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext); + } } /* reset for the next loop around, unless overridden later */ @@ -982,10 +986,12 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags, if (res == -1) { ast_autochan_destroy(autochan); + iter = ast_channel_iterator_destroy(iter); goto exit; } else if (res == -2) { res = 0; ast_autochan_destroy(autochan); + iter = ast_channel_iterator_destroy(iter); goto exit; } else if (res > 1 && spec) { struct ast_channel *next; @@ -1005,6 +1011,7 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags, } } } else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) { + iter = ast_channel_iterator_destroy(iter); goto exit; } } diff --git a/apps/app_queue.c b/apps/app_queue.c index 0f192acb6..84f075751 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1426,9 +1426,9 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime); break; } else { - ao2_unlock(q); ao2_ref(member, -1); ao2_iterator_destroy(&mem_iter); + ao2_unlock(q); ast_debug(4, "%s is available.\n", member->membername); return 0; } @@ -4560,24 +4560,24 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces; if (!tmp) { ao2_ref(cur, -1); - ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); + ao2_unlock(qe->parent); goto out; } if (!datastore) { if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) { + callattempt_free(tmp); ao2_ref(cur, -1); - ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - callattempt_free(tmp); + ao2_unlock(qe->parent); goto out; } datastore->inheritance = DATASTORE_INHERIT_FOREVER; if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) { + callattempt_free(tmp); ao2_ref(cur, -1); - ao2_unlock(&qe->parent); ao2_iterator_destroy(&memi); - callattempt_free(tmp); + ao2_unlock(&qe->parent); goto out; } datastore->data = dialed_interfaces; @@ -4601,6 +4601,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce if (di) { callattempt_free(tmp); + ao2_ref(cur, -1); continue; } @@ -4610,10 +4611,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce * it won't call one that has already been called. */ if (strncasecmp(cur->interface, "Local/", 6)) { if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) { + callattempt_free(tmp); ao2_ref(cur, -1); - ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - callattempt_free(tmp); + ao2_unlock(qe->parent); goto out; } strcpy(di->interface, cur->interface); @@ -6623,9 +6624,10 @@ static int queue_function_queuememberlist(struct ast_channel *chan, const char * 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); + struct ao2_iterator mem_iter; ao2_lock(q); + mem_iter = ao2_iterator_init(q->members, 0); while ((m = ao2_iterator_next(&mem_iter))) { /* strcat() is always faster than printf() */ if (count++) { @@ -7148,7 +7150,9 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena static int clear_stats(const char *queuename) { struct call_queue *q; - struct ao2_iterator queue_iter = ao2_iterator_init(queues, 0); + struct ao2_iterator queue_iter; + + queue_iter = ao2_iterator_init(queues, 0); while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { ao2_lock(q); if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) @@ -7237,8 +7241,8 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char * } } - queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK); ao2_lock(queues); + queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK); while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { float sl; struct call_queue *realtime_queue = NULL; @@ -7967,11 +7971,11 @@ static char *complete_queue_remove_member(const char *line, const char *word, in while ((m = ao2_iterator_next(&mem_iter))) { if (!strncasecmp(word, m->membername, wordlen) && ++which > state) { char *tmp; - ao2_unlock(q); tmp = ast_strdup(m->interface); ao2_ref(m, -1); - queue_t_unref(q, "Done with iterator, returning interface name"); ao2_iterator_destroy(&mem_iter); + ao2_unlock(q); + queue_t_unref(q, "Done with iterator, returning interface name"); ao2_iterator_destroy(&queue_iter); return tmp; } @@ -8524,6 +8528,7 @@ static void queues_data_provider_get_helper(const struct ast_data_search *search ao2_ref(member, -1); } + ao2_iterator_destroy(&im); /* include the callers inside the result. */ if (queue->head) { diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 2255801c0..9d442d5a0 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -2636,6 +2636,7 @@ static char *handle_cli_iax2_show_callno_limits(struct ast_cli_entry *e, int cmd sin.sin_addr.s_addr = peercnt->addr; if (a->argc == 5 && (!strcasecmp(a->argv[4], ast_inet_ntoa(sin.sin_addr)))) { ast_cli(a->fd, "%-15s %-12d %-12d\n", ast_inet_ntoa(sin.sin_addr), peercnt->cur, peercnt->limit); + ao2_ref(peercnt, -1); found = 1; break; } else { @@ -6680,8 +6681,7 @@ static char *handle_cli_iax2_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli(a->fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); i = ao2_iterator_init(users, 0); - for (user = ao2_iterator_next(&i); user; - user_unref(user), user = ao2_iterator_next(&i)) { + for (; (user = ao2_iterator_next(&i)); user_unref(user)) { if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) continue; @@ -6769,8 +6769,7 @@ static int __iax2_show_peers(int fd, int *total, struct mansession *s, const int ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", "Description"); i = ao2_iterator_init(peers, 0); - for (peer = ao2_iterator_next(&i); peer; - peer_unref(peer), peer = ao2_iterator_next(&i)) { + for (; (peer = ao2_iterator_next(&i)); peer_unref(peer)) { char nm[20]; char status[20]; int retstatus; @@ -7093,7 +7092,7 @@ static int manager_iax2_show_peer_list(struct mansession *s, const struct messag i = ao2_iterator_init(peers, 0); - for (peer = ao2_iterator_next(&i); peer; peer_unref(peer), peer = ao2_iterator_next(&i)) { + for (; (peer = ao2_iterator_next(&i)); peer_unref(peer)) { encmethods_to_str(peer->encmethods, encmethods); astman_append(s, "Event: PeerEntry\r\n%sChanneltype: IAX\r\n", idtext); if (!ast_strlen_zero(peer->username)) { @@ -7676,8 +7675,8 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies return res; } /* Search the userlist for a compatible entry, and fill in the rest */ - i = ao2_iterator_init(users, 0); ast_sockaddr_from_sin(&addr, sin); + i = ao2_iterator_init(users, 0); while ((user = ao2_iterator_next(&i))) { if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ @@ -14681,10 +14680,9 @@ static int users_data_provider_get(const struct ast_data_search *search, char *pstr = ""; i = ao2_iterator_init(users, 0); - while ((user = ao2_iterator_next(&i))) { + for (; (user = ao2_iterator_next(&i)); user_unref(user)) { data_user = ast_data_add_node(data_root, "user"); if (!data_user) { - user_unref(user); continue; } @@ -14733,8 +14731,6 @@ static int users_data_provider_get(const struct ast_data_search *search, } ast_data_add_str(data_user, "codec-preferences", pstr); - user_unref(user); - if (!ast_data_search_match(search, data_user)) { ast_data_remove_node(data_root, data_user); } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a5634fe94..73a4b7400 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -17639,8 +17639,8 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli while ((pi = ao2_t_iterator_next(&i, "iterate thru peers table"))) { ao2_lock(pi); if (name && regexec(®exbuf, pi->name, 0, NULL, 0)) { - sip_unref_peer(pi, "toss iterator peer ptr before continue"); ao2_unlock(pi); + sip_unref_peer(pi, "toss iterator peer ptr before continue"); continue; }; if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { @@ -31103,6 +31103,8 @@ static int peers_data_provider_get(const struct ast_data_search *search, /* transfer mode */ enum_node = ast_data_add_node(data_peer, "allowtransfer"); if (!enum_node) { + ao2_unlock(peer); + ao2_ref(peer, -1); continue; } ast_data_add_str(enum_node, "text", transfermode2str(peer->allowtransfer)); @@ -31142,6 +31144,8 @@ static int peers_data_provider_get(const struct ast_data_search *search, /* amaflags */ enum_node = ast_data_add_node(data_peer, "amaflags"); if (!enum_node) { + ao2_unlock(peer); + ao2_ref(peer, -1); continue; } ast_data_add_int(enum_node, "value", peer->amaflags); @@ -31150,6 +31154,8 @@ static int peers_data_provider_get(const struct ast_data_search *search, /* sip options */ data_sip_options = ast_data_add_node(data_peer, "sipoptions"); if (!data_sip_options) { + ao2_unlock(peer); + ao2_ref(peer, -1); continue; } for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { @@ -31159,6 +31165,8 @@ static int peers_data_provider_get(const struct ast_data_search *search, /* callingpres */ enum_node = ast_data_add_node(data_peer, "callingpres"); if (!enum_node) { + ao2_unlock(peer); + ao2_ref(peer, -1); continue; } ast_data_add_int(enum_node, "value", peer->callingpres); diff --git a/include/asterisk/indications.h b/include/asterisk/indications.h index 13422d92b..b02be1fdf 100644 --- a/include/asterisk/indications.h +++ b/include/asterisk/indications.h @@ -176,7 +176,8 @@ int ast_tone_zone_count(void); /*! * \brief Get an iterator for the available tone zones * - * Use ao2_iterator_next() to iterate the tone zones. + * \note Use ao2_iterator_next() to iterate the tone zones. + * \note Use ao2_iterator_destroy() to clean up. * * \return an initialized iterator */ diff --git a/main/indications.c b/main/indications.c index ef98407f5..b07de4bc4 100644 --- a/main/indications.c +++ b/main/indications.c @@ -658,6 +658,7 @@ static char *complete_country(struct ast_cli_args *a) break; } } + ao2_iterator_destroy(&i); return res; } @@ -835,6 +836,7 @@ static char *handle_cli_indication_show(struct ast_cli_entry *e, int cmd, struct ast_tone_zone_unlock(tz); tz = ast_tone_zone_unref(tz); } + ao2_iterator_destroy(&iter); return CLI_SUCCESS; } diff --git a/main/pbx.c b/main/pbx.c index 204eb8841..e565c480f 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -7605,6 +7605,7 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_ AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list); } } + ao2_iterator_destroy(&i); /* save the old table and list */ oldtable = contexts_table; diff --git a/main/taskprocessor.c b/main/taskprocessor.c index e0d7e5b94..782a34451 100644 --- a/main/taskprocessor.c +++ b/main/taskprocessor.c @@ -173,6 +173,7 @@ static char *tps_taskprocessor_tab_complete(struct ast_taskprocessor *p, struct } ao2_ref(p, -1); } + ao2_iterator_destroy(&i); return name; } @@ -266,6 +267,7 @@ static char *cli_tps_report(struct ast_cli_entry *e, int cmd, struct ast_cli_arg ast_cli(a->fd, "\n%24s %17ld %12ld %12ld", name, processed, qsize, maxqsize); ao2_ref(p, -1); } + ao2_iterator_destroy(&i); tcount = ao2_container_count(tps_singletons); ast_cli(a->fd, "\n\t+---------------------+-----------------+------------+-------------+\n\t%d taskprocessors\n\n", tcount); return CLI_SUCCESS; diff --git a/res/res_odbc.c b/res/res_odbc.c index 1770bb303..463bf9fdb 100644 --- a/res/res_odbc.c +++ b/res/res_odbc.c @@ -911,7 +911,7 @@ static int load_odbc_config(void) static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - struct ao2_iterator aoi = ao2_iterator_init(class_container, 0); + struct ao2_iterator aoi; struct odbc_class *class; struct odbc_obj *current; int length = 0; @@ -930,6 +930,7 @@ static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_c if (a->pos != 2) return NULL; length = strlen(a->word); + aoi = ao2_iterator_init(class_container, 0); while ((class = ao2_iterator_next(&aoi))) { if (!strncasecmp(a->word, class->name, length) && ++which > a->n) { ret = ast_strdup(class->name); @@ -1722,12 +1723,14 @@ static int data_odbc_provider_handler(const struct ast_data_search *search, ao2_ref(current, -1); } + ao2_iterator_destroy(&aoi2); ao2_ref(class, -1); if (!ast_data_search_match(search, data_odbc_class)) { ast_data_remove_node(root, data_odbc_class); } } + ao2_iterator_destroy(&aoi); return 0; } diff --git a/res/res_srtp.c b/res/res_srtp.c index a232314fa..a22a02089 100644 --- a/res/res_srtp.c +++ b/res/res_srtp.c @@ -322,7 +322,7 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt int retry = 0; struct ast_rtp_instance_stats stats = {0,}; - tryagain: +tryagain: for (i = 0; i < 2; i++) { res = rtcp ? srtp_unprotect_rtcp(srtp->session, buf, len) : srtp_unprotect(srtp->session, buf, len); @@ -348,38 +348,42 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt if (srtp->session) { struct ast_srtp_policy *policy; struct ao2_iterator it; - int policies_count = 0; - + int policies_count; + // dealloc first ast_log(LOG_WARNING, "SRTP destroy before re-create\n"); srtp_dealloc(srtp->session); - + // get the count policies_count = ao2_container_count(srtp->policies); - + // get the first to build up it = ao2_iterator_init(srtp->policies, 0); policy = ao2_iterator_next(&it); ast_log(LOG_WARNING, "SRTP try to re-create\n"); - if (srtp_create(&srtp->session, &policy->sp) == err_status_ok) { - ast_log(LOG_WARNING, "SRTP re-created with first policy\n"); - - // unref first element - ao2_t_ref(policy, -1, "Unreffing first policy for re-creating srtp session"); - - // if we have more than one policy, add them afterwards - if (policies_count > 1) { - ast_log(LOG_WARNING, "Add all the other %d policies\n", policies_count-1); - while ((policy = ao2_iterator_next(&it))) { - srtp_add_stream(srtp->session, &policy->sp); - ao2_t_ref(policy, -1, "Unreffing n-th policy for re-creating srtp session"); + if (policy) { + if (srtp_create(&srtp->session, &policy->sp) == err_status_ok) { + ast_log(LOG_WARNING, "SRTP re-created with first policy\n"); + + // unref first element + ao2_t_ref(policy, -1, "Unreffing first policy for re-creating srtp session"); + + // if we have more than one policy, add them afterwards + if (policies_count > 1) { + ast_log(LOG_WARNING, "Add all the other %d policies\n", + policies_count - 1); + while ((policy = ao2_iterator_next(&it))) { + srtp_add_stream(srtp->session, &policy->sp); + ao2_t_ref(policy, -1, "Unreffing n-th policy for re-creating srtp session"); + } } + + retry++; + ao2_iterator_destroy(&it); + goto tryagain; } - - retry++; - ao2_iterator_destroy(&it); - goto tryagain; + ao2_t_ref(policy, -1, "Unreffing first policy after srtp_create failed"); } ao2_iterator_destroy(&it); } diff --git a/res/snmp/agent.c b/res/snmp/agent.c index 153106e0d..71f02134f 100644 --- a/res/snmp/agent.c +++ b/res/snmp/agent.c @@ -703,6 +703,7 @@ static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *lengt tz = ast_tone_zone_unref(tz); long_ret++; } + ao2_iterator_destroy(&i); return (u_char *) &long_ret; } @@ -743,6 +744,7 @@ static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t tz = ast_tone_zone_unref(tz); i--; } + ao2_iterator_destroy(&iter); if (tz == NULL) { return NULL; @@ -750,24 +752,27 @@ static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t switch (vp->magic) { case ASTINDINDEX: + ast_tone_zone_unref(tz); long_ret = name[*length - 1]; return (u_char *)&long_ret; case ASTINDCOUNTRY: ast_copy_string(ret_buf, tz->country, sizeof(ret_buf)); - tz = ast_tone_zone_unref(tz); + ast_tone_zone_unref(tz); *var_len = strlen(ret_buf); return (u_char *) ret_buf; case ASTINDALIAS: /* No longer exists */ + ast_tone_zone_unref(tz); return NULL; case ASTINDDESCRIPTION: ast_tone_zone_lock(tz); ast_copy_string(ret_buf, tz->description, sizeof(ret_buf)); ast_tone_zone_unlock(tz); - tz = ast_tone_zone_unref(tz); + ast_tone_zone_unref(tz); *var_len = strlen(ret_buf); return (u_char *) ret_buf; default: + ast_tone_zone_unref(tz); break; } return NULL; |