summaryrefslogtreecommitdiff
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
authorCorey Farrell <git@cfware.com>2016-12-08 21:00:02 -0500
committerCorey Farrell <git@cfware.com>2016-12-17 11:25:40 -0500
commit8fbb384ea2f0f5e648f8137c2b77104e910a34d9 (patch)
tree960d063190d450f1c6dcf3d8e301519becbbb053 /channels/chan_sip.c
parent19328de2ab1317e75a7bf4cb6ebf9fce55cb05e1 (diff)
chan_sip: Reorder unload_module to deal with stuck TCP threads.
In some situations TCP threads may become frozen. This creates the possibility that Asterisk could segfault if they become unfrozen after chan_sip has been dlclose'd. This reorders the unload_module process to allow abort if threads do not exit within 5 seconds. High level order as follows: 1) Unregister from the core to stop new requests. 2) Signal threads to stop 3) Clear config based tables (but do not free the table itself). 4) Verify that threads have shutdown, cancel unload if not. 5) Clean all remaining resources. ASTERISK-26586 Change-Id: Ie23692041d838fbd35ece61868f4c640960ff882
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c54
1 files changed, 27 insertions, 27 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index aa0d6a5dd..af17a386f 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1780,7 +1780,7 @@ static void destroy_escs(void)
{
int i;
for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) {
- ao2_cleanup(event_state_compositors[i].compositor);
+ ao2_replace(event_state_compositors[i].compositor, NULL);
}
}
@@ -35365,6 +35365,8 @@ static int unload_module(void)
struct ao2_iterator i;
struct timeval start;
+ ast_sched_dump(sched);
+
ast_sip_api_provider_unregister();
if (sip_cfg.websocket_enabled) {
@@ -35374,12 +35376,11 @@ static int unload_module(void)
network_change_stasis_unsubscribe();
acl_change_event_stasis_unsubscribe();
- ast_sched_dump(sched);
-
/* First, take us out of the channel type list */
ast_channel_unregister(&sip_tech);
-
ast_msg_tech_unregister(&sip_msg_tech);
+ ast_cc_monitor_unregister(&sip_cc_monitor_callbacks);
+ ast_cc_agent_unregister(&sip_cc_agent_callbacks);
/* Unregister dial plan functions */
ast_custom_function_unregister(&sippeer_function);
@@ -35443,8 +35444,6 @@ static int unload_module(void)
}
ao2_iterator_destroy(&i);
- unlink_all_peers_from_tables();
-
ast_mutex_lock(&monlock);
if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
pthread_t th = monitor_thread;
@@ -35458,7 +35457,12 @@ static int unload_module(void)
ast_mutex_unlock(&monlock);
}
+ /* Clear containers */
+ unlink_all_peers_from_tables();
cleanup_all_regs();
+ sip_epa_unregister_all();
+ destroy_escs();
+ clear_sip_domains();
{
struct ao2_iterator iter;
@@ -35487,6 +35491,23 @@ static int unload_module(void)
*/
ast_sched_runq(sched);
+ /*
+ * Wait awhile for the TCP/TLS thread container to become empty.
+ *
+ * XXX This is a hack, but the worker threads cannot be created
+ * joinable. They can die on their own and remove themselves
+ * from the container thus resulting in a huge memory leak.
+ */
+ start = ast_tvnow();
+ while (ao2_container_count(threadt) && (ast_tvdiff_sec(ast_tvnow(), start) < 5)) {
+ sched_yield();
+ }
+ if (ao2_container_count(threadt)) {
+ ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
+
+ return -1;
+ }
+
/* Free memory for local network address mask */
ast_free_ha(localaddr);
@@ -35497,9 +35518,6 @@ static int unload_module(void)
}
ast_mutex_unlock(&authl_lock);
- sip_epa_unregister_all();
- destroy_escs();
-
ast_free(default_tls_cfg.certfile);
ast_free(default_tls_cfg.pvtfile);
ast_free(default_tls_cfg.cipher);
@@ -35508,21 +35526,6 @@ static int unload_module(void)
ast_rtp_dtls_cfg_free(&default_dtls_cfg);
- /*
- * Wait awhile for the TCP/TLS thread container to become empty.
- *
- * XXX This is a hack, but the worker threads cannot be created
- * joinable. They can die on their own and remove themselves
- * from the container thus resulting in a huge memory leak.
- */
- start = ast_tvnow();
- while (ao2_container_count(threadt) && (ast_tvdiff_sec(ast_tvnow(), start) < 5)) {
- sched_yield();
- }
- if (ao2_container_count(threadt)) {
- ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
- }
-
ao2_cleanup(registry_list);
ao2_cleanup(subscription_mwi_list);
@@ -35536,7 +35539,6 @@ static int unload_module(void)
ao2_t_cleanup(threadt, "unref the thread table");
ao2_t_cleanup(sip_monitor_instances, "unref the sip_monitor_instances table");
- clear_sip_domains();
sip_cfg.contact_acl = ast_free_acl_list(sip_cfg.contact_acl);
if (sipsock_read_id) {
ast_io_remove(io, sipsock_read_id);
@@ -35549,8 +35551,6 @@ static int unload_module(void)
ast_context_destroy_by_name(used_context, "SIP");
ast_unload_realtime("sipregs");
ast_unload_realtime("sippeers");
- ast_cc_monitor_unregister(&sip_cc_monitor_callbacks);
- ast_cc_agent_unregister(&sip_cc_agent_callbacks);
sip_reqresp_parser_exit();
sip_unregister_tests();