From 52f0932e4c6d4446afbbf0f0ffa0ac8f50593ff4 Mon Sep 17 00:00:00 2001
From: Richard Mudgett <rmudgett@digium.com>
Date: Thu, 10 Mar 2016 21:54:03 -0600
Subject: [PATCH] chan_sip.c: Clear scheduled immediate events on unload.

This patch is part of a series to resolve deadlocks in chan_sip.c.

The reordering of chan_sip's shutdown is to handle any immediate events
that get put onto the scheduler so resources aren't leaked.  The typical
immediate events at this time are going to be concerned with stopping
other scheduled events.

ASTERISK-25023

Change-Id: I3f6540717634f6f2e84d8531a054976f2bbb9d20
---
 channels/chan_sip.c | 53 ++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index a8d5032062..2719372089 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -34879,6 +34879,26 @@ static int unload_module(void)
 		ast_mutex_unlock(&monlock);
 	}
 
+	cleanup_all_regs();
+
+	{
+		struct ao2_iterator iter;
+		struct sip_subscription_mwi *iterator;
+
+		iter = ao2_iterator_init(subscription_mwi_list, 0);
+		while ((iterator = ao2_t_iterator_next(&iter, "unload_module iter"))) {
+			ao2_lock(iterator);
+			if (iterator->dnsmgr) {
+				ast_dnsmgr_release(iterator->dnsmgr);
+				iterator->dnsmgr = NULL;
+				ao2_t_ref(iterator, -1, "dnsmgr release");
+			}
+			ao2_unlock(iterator);
+			ao2_t_ref(iterator, -1, "unload_module iter");
+		}
+		ao2_iterator_destroy(&iter);
+	}
+
 	/* Destroy all the dialogs and free their memory */
 	i = ao2_iterator_init(dialogs, 0);
 	while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) {
@@ -34887,6 +34907,13 @@ static int unload_module(void)
 	}
 	ao2_iterator_destroy(&i);
 
+	/*
+	 * Since the monitor thread runs the scheduled events and we
+	 * just stopped the monitor thread above, we have to run any
+	 * pending scheduled immediate events in this thread.
+	 */
+	ast_sched_runq(sched);
+
 	/* Free memory for local network address mask */
 	ast_free_ha(localaddr);
 
@@ -34908,28 +34935,6 @@ static int unload_module(void)
 
 	ast_rtp_dtls_cfg_free(&default_dtls_cfg);
 
-	cleanup_all_regs();
-	ao2_cleanup(registry_list);
-
-	{
-		struct ao2_iterator iter;
-		struct sip_subscription_mwi *iterator;
-
-		iter = ao2_iterator_init(subscription_mwi_list, 0);
-		while ((iterator = ao2_t_iterator_next(&iter, "unload_module iter"))) {
-			ao2_lock(iterator);
-			if (iterator->dnsmgr) {
-				ast_dnsmgr_release(iterator->dnsmgr);
-				iterator->dnsmgr = NULL;
-				ao2_t_ref(iterator, -1, "dnsmgr release");
-			}
-			ao2_unlock(iterator);
-			ao2_t_ref(iterator, -1, "unload_module iter");
-		}
-		ao2_iterator_destroy(&iter);
-	}
-	ao2_cleanup(subscription_mwi_list);
-
 	/*
 	 * Wait awhile for the TCP/TLS thread container to become empty.
 	 *
@@ -34945,6 +34950,9 @@ static int unload_module(void)
 		ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
 	}
 
+	ao2_cleanup(registry_list);
+	ao2_cleanup(subscription_mwi_list);
+
 	ao2_t_global_obj_release(g_bogus_peer, "Release the bogus peer.");
 
 	ao2_t_cleanup(peers, "unref the peers table");
@@ -34964,6 +34972,7 @@ static int unload_module(void)
 	close(sipsock);
 	io_context_destroy(io);
 	ast_sched_context_destroy(sched);
+	sched = NULL;
 	ast_context_destroy_by_name(used_context, "SIP");
 	ast_unload_realtime("sipregs");
 	ast_unload_realtime("sippeers");
-- 
GitLab