From: Corey Farrell Date: Thu, 19 Feb 2015 01:59:05 +0000 (+0000) Subject: Create work around for scheduler leaks during shutdown. X-Git-Tag: 11.17.0-rc1~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f8254210de32c50aebc6987e750ff1c788924c23;p=thirdparty%2Fasterisk.git Create work around for scheduler leaks during shutdown. * Added ast_sched_clean_by_callback for cleanup of scheduled events that have not yet fired. * Run all pending peercnt_remove_cb and replace_callno events in chan_iax2. Cleanup of replace_callno events is only run 11, since it no longer releases any references or allocations in 13+. ASTERISK-24451 #close Reported by: Corey Farrell Review: https://reviewboard.asterisk.org/r/4425/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@431916 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index de949571bc..35d54028c2 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -14837,18 +14837,21 @@ static int __unload_module(void) ao2_ref(users, -1); ao2_ref(iax_peercallno_pvts, -1); ao2_ref(iax_transfercallno_pvts, -1); - ao2_ref(peercnts, -1); ao2_ref(callno_limits, -1); ao2_ref(calltoken_ignores, -1); - ao2_ref(callno_pool, -1); - ao2_ref(callno_pool_trunk, -1); if (timer) { ast_timer_close(timer); timer = NULL; } transmit_processor = ast_taskprocessor_unreference(transmit_processor); + + ast_sched_clean_by_callback(sched, peercnt_remove_cb, peercnt_remove_cb); + ast_sched_clean_by_callback(sched, replace_callno, replace_callno); ast_sched_context_destroy(sched); sched = NULL; + ao2_ref(peercnts, -1); + ao2_ref(callno_pool, -1); + ao2_ref(callno_pool_trunk, -1); con = ast_context_find(regcontext); if (con) diff --git a/include/asterisk/sched.h b/include/asterisk/sched.h index aac6dc82b1..256d06769e 100644 --- a/include/asterisk/sched.h +++ b/include/asterisk/sched.h @@ -170,6 +170,17 @@ void ast_sched_context_destroy(struct ast_sched_context *c); typedef int (*ast_sched_cb)(const void *data); #define AST_SCHED_CB(a) ((ast_sched_cb)(a)) +/*! + * \brief Clean all scheduled events with matching callback. + * + * \param con Scheduler Context + * \param match Callback to match + * \param cleanup_cb Callback to run + * + * \note The return of cleanup_cb is ignored. No events are rescheduled. + */ +void ast_sched_clean_by_callback(struct ast_sched_context *con, ast_sched_cb match, ast_sched_cb cleanup_cb); + struct ast_cb_names { int numassocs; char *list[10]; diff --git a/main/sched.c b/main/sched.c index a67f2f826d..8f6bbf9216 100644 --- a/main/sched.c +++ b/main/sched.c @@ -295,6 +295,31 @@ static void sched_release(struct ast_sched_context *con, struct sched *tmp) ast_free(tmp); } +void ast_sched_clean_by_callback(struct ast_sched_context *con, ast_sched_cb match, ast_sched_cb cleanup_cb) +{ + int i = 1; + struct sched *current; + + ast_mutex_lock(&con->lock); + while ((current = ast_heap_peek(con->sched_heap, i))) { + if (current->callback != match) { + i++; + continue; + } + + ast_heap_remove(con->sched_heap, current); + if (!ast_hashtab_remove_this_object(con->schedq_ht, current)) { + ast_log(LOG_ERROR,"Sched entry %d was in the schedq list but not in the hashtab???\n", current->id); + } + + con->schedcnt--; + + cleanup_cb(current->data); + sched_release(con, current); + } + ast_mutex_unlock(&con->lock); +} + /*! \brief * Return the number of milliseconds * until the next scheduled event