diff options
author | Joshua Colp <jcolp@digium.com> | 2016-10-19 08:31:42 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2016-10-19 08:31:42 -0500 |
commit | 1bde92f68c7db787734c637ed9b4d54c573a2813 (patch) | |
tree | 098ad665a87e658d08d60ea12faf8d58fcf19861 | |
parent | 6adc293b14f22f273c2f00f8a7b33f4f6aefaf51 (diff) | |
parent | 012fda29d23bac1d2b06e9a8933980047da30246 (diff) |
Merge "CDR: Alter destruction pattern for CDR chains." into 13
-rw-r--r-- | main/cdr.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/main/cdr.c b/main/cdr.c index ab6530ed3..5e515d823 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -695,6 +695,7 @@ struct cdr_object { ); struct cdr_object *next; /*!< The next CDR object in the chain */ struct cdr_object *last; /*!< The last CDR object in the chain */ + int is_root; /*!< True if this is the first CDR in the chain */ }; /*! @@ -850,7 +851,22 @@ static void cdr_object_dtor(void *obj) } ast_string_field_free_memory(cdr); - ao2_cleanup(cdr->next); + /* CDR destruction used to work by calling ao2_cleanup(next) and + * allowing the chain to destroy itself neatly. Unfortunately, for + * really long chains, this can result in a stack overflow. So now + * when the root CDR is destroyed, it is responsible for unreffing + * all CDRs in the chain + */ + if (cdr->is_root) { + struct cdr_object *curr = cdr->next; + struct cdr_object *next; + + while (curr) { + next = curr->next; + ao2_cleanup(curr); + curr = next; + } + } } /*! @@ -2094,6 +2110,7 @@ static void handle_channel_cache_message(void *data, struct stasis_subscription if (!cdr) { return; } + cdr->is_root = 1; ao2_link(active_cdrs_by_channel, cdr); } |