]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Create work around for scheduler leaks during shutdown.
authorCorey Farrell <git@cfware.com>
Thu, 19 Feb 2015 01:59:05 +0000 (01:59 +0000)
committerCorey Farrell <git@cfware.com>
Thu, 19 Feb 2015 01:59:05 +0000 (01:59 +0000)
* 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

channels/chan_iax2.c
include/asterisk/sched.h
main/sched.c

index de949571bc6e6029e4fd000cf3e91866519743eb..35d54028c20f1c94ce482c4de1968bab828e0892 100644 (file)
@@ -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)
index aac6dc82b1ff3a4837bf6b178cfccd723a3b1af1..256d06769e1bdda600a97797e5ba87a148fa97d1 100644 (file)
@@ -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];
index a67f2f826d352b76282c358ffb7e55df8da176e1..8f6bbf9216508a584dc79199c9360e1982036b54 100644 (file)
@@ -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