diff options
author | Corey Farrell <git@cfware.com> | 2016-12-08 21:00:02 -0500 |
---|---|---|
committer | Corey Farrell <git@cfware.com> | 2016-12-17 11:25:40 -0500 |
commit | 8fbb384ea2f0f5e648f8137c2b77104e910a34d9 (patch) | |
tree | 960d063190d450f1c6dcf3d8e301519becbbb053 | |
parent | 19328de2ab1317e75a7bf4cb6ebf9fce55cb05e1 (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
-rw-r--r-- | channels/chan_sip.c | 54 |
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(); |