summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJenkins2 <jenkins2@gerrit.asterisk.org>2018-02-12 16:03:46 -0600
committerGerrit Code Review <gerrit2@gerrit.digium.api>2018-02-12 16:03:46 -0600
commit0461286123e3ab201374f8b8a2435ed6006b7a5a (patch)
treea1a515d40e8a370da6487204c7ecbdd0d7c51eba /main
parentc86ed5a69d4837f9d9cf6c2463adb987d6225bed (diff)
parentb2fcb30d388ae7ec0c51a9719f54de006ad2478f (diff)
Merge "cdr.c: Fix runtime leak of CDR records."
Diffstat (limited to 'main')
-rw-r--r--main/cdr.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/main/cdr.c b/main/cdr.c
index 8acae607f..4acadf975 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -371,7 +371,7 @@ static ast_cond_t cdr_pending_cond;
/*! \brief A container of the active master CDRs indexed by Party A channel uniqueid */
static struct ao2_container *active_cdrs_master;
-/*! \brief A container of all active CDRs indexed by Party B channel name */
+/*! \brief A container of all active CDRs with a Party B indexed by Party B channel name */
static struct ao2_container *active_cdrs_all;
/*! \brief Message router for stasis messages regarding channel state */
@@ -971,13 +971,21 @@ static void cdr_all_unlink(struct cdr_object *cdr)
ast_assert(cdr->is_root);
+ /* Hold a ref to the root CDR to ensure the list members don't go away on us. */
+ ao2_ref(cdr, +1);
ao2_lock(active_cdrs_all);
- for (cur = cdr->next; cur; cur = next) {
+ for (cur = cdr; cur; cur = next) {
next = cur->next;
ao2_unlink_flags(active_cdrs_all, cur, OBJ_NOLOCK);
+ /*
+ * It is safe to still use cur after unlinking because the
+ * root CDR holds a ref to all the CDRs in the list and we
+ * have a ref to the root CDR.
+ */
ast_string_field_set(cur, party_b_name, "");
}
ao2_unlock(active_cdrs_all);
+ ao2_ref(cdr, -1);
}
/*!