mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
Fix worker thread resource leak in SIP TCP/TLS.
The SIP TCP/TLS worker threads were created joinable but noone could join them if they died on their own. * Fix the SIP TCP/TLS worker threads to not be created joinable. * _sip_tcp_helper_thread() only needs one parameter since the pvt parameter is only passed in as NULL and never used. (closes issue ASTERISK-19203) Reported by: Steve Davies Review: https://reviewboard.asterisk.org/r/1714/ ........ Merged revisions 356677 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 356690 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@356697 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1510,7 +1510,7 @@ static int get_domain(const char *str, char *domain, int len);
|
||||
static void get_realm(struct sip_pvt *p, const struct sip_request *req);
|
||||
|
||||
/*-- TCP connection handling ---*/
|
||||
static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session);
|
||||
static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_session);
|
||||
static void *sip_tcp_worker_fn(void *);
|
||||
|
||||
/*--- Constructing requests and responses */
|
||||
@@ -2488,7 +2488,7 @@ static void *sip_tcp_worker_fn(void *data)
|
||||
{
|
||||
struct ast_tcptls_session_instance *tcptls_session = data;
|
||||
|
||||
return _sip_tcp_helper_thread(NULL, tcptls_session);
|
||||
return _sip_tcp_helper_thread(tcptls_session);
|
||||
}
|
||||
|
||||
/*! \brief Check if the authtimeout has expired.
|
||||
@@ -2519,7 +2519,7 @@ static int sip_check_authtimeout(time_t start)
|
||||
/*! \brief SIP TCP thread management function
|
||||
This function reads from the socket, parses the packet into a request
|
||||
*/
|
||||
static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session)
|
||||
static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_session)
|
||||
{
|
||||
int res, cl, timeout = -1, authenticated = 0, flags, after_poll = 0, need_poll = 1;
|
||||
time_t start;
|
||||
@@ -26483,6 +26483,7 @@ static int sip_prepare_socket(struct sip_pvt *p)
|
||||
struct ast_tcptls_session_instance *tcptls_session;
|
||||
struct ast_tcptls_session_args *ca;
|
||||
struct ast_sockaddr sa_tmp;
|
||||
pthread_t launched;
|
||||
|
||||
/* check to see if a socket is already active */
|
||||
if ((s->fd != -1) && (s->type == SIP_TRANSPORT_UDP)) {
|
||||
@@ -26507,7 +26508,7 @@ static int sip_prepare_socket(struct sip_pvt *p)
|
||||
}
|
||||
|
||||
/* At this point we are dealing with a TCP/TLS connection
|
||||
* 1. We need to check to see if a connectin thread exists
|
||||
* 1. We need to check to see if a connection thread exists
|
||||
* for this address, if so use that.
|
||||
* 2. If a thread does not exist for this address, but the tcptls_session
|
||||
* exists on the socket, the connection was closed.
|
||||
@@ -26578,7 +26579,7 @@ static int sip_prepare_socket(struct sip_pvt *p)
|
||||
/* Give the new thread a reference to the tcptls_session */
|
||||
ao2_ref(s->tcptls_session, +1);
|
||||
|
||||
if (ast_pthread_create_background(&ca->master, NULL, sip_tcp_worker_fn, s->tcptls_session)) {
|
||||
if (ast_pthread_create_detached_background(&launched, NULL, sip_tcp_worker_fn, s->tcptls_session)) {
|
||||
ast_debug(1, "Unable to launch '%s'.", ca->name);
|
||||
ao2_ref(s->tcptls_session, -1); /* take away the thread ref we just gave it */
|
||||
goto create_tcptls_session_fail;
|
||||
@@ -31578,6 +31579,7 @@ static int unload_module(void)
|
||||
struct sip_threadinfo *th;
|
||||
struct ast_context *con;
|
||||
struct ao2_iterator i;
|
||||
int wait_count;
|
||||
|
||||
network_change_event_unsubscribe();
|
||||
|
||||
@@ -31636,7 +31638,6 @@ static int unload_module(void)
|
||||
pthread_t thread = th->threadid;
|
||||
th->stop = 1;
|
||||
pthread_kill(thread, SIGURG);
|
||||
pthread_join(thread, NULL);
|
||||
ao2_t_ref(th, -1, "decrement ref from iterator");
|
||||
}
|
||||
ao2_iterator_destroy(&i);
|
||||
@@ -31682,21 +31683,11 @@ static int unload_module(void)
|
||||
sip_epa_unregister_all();
|
||||
destroy_escs();
|
||||
|
||||
if (default_tls_cfg.certfile) {
|
||||
ast_free(default_tls_cfg.certfile);
|
||||
}
|
||||
if (default_tls_cfg.pvtfile) {
|
||||
ast_free(default_tls_cfg.pvtfile);
|
||||
}
|
||||
if (default_tls_cfg.cipher) {
|
||||
ast_free(default_tls_cfg.cipher);
|
||||
}
|
||||
if (default_tls_cfg.cafile) {
|
||||
ast_free(default_tls_cfg.cafile);
|
||||
}
|
||||
if (default_tls_cfg.capath) {
|
||||
ast_free(default_tls_cfg.capath);
|
||||
}
|
||||
ast_free(default_tls_cfg.certfile);
|
||||
ast_free(default_tls_cfg.pvtfile);
|
||||
ast_free(default_tls_cfg.cipher);
|
||||
ast_free(default_tls_cfg.cafile);
|
||||
ast_free(default_tls_cfg.capath);
|
||||
|
||||
cleanup_all_regs();
|
||||
ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy);
|
||||
@@ -31714,6 +31705,21 @@ static int unload_module(void)
|
||||
ASTOBJ_CONTAINER_DESTROYALL(&submwil, sip_subscribe_mwi_destroy);
|
||||
ASTOBJ_CONTAINER_DESTROY(&submwil);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
wait_count = 1000;
|
||||
while (ao2_container_count(threadt) && --wait_count) {
|
||||
sched_yield();
|
||||
}
|
||||
if (!wait_count) {
|
||||
ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
|
||||
}
|
||||
|
||||
ao2_t_ref(peers, -1, "unref the peers table");
|
||||
ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table");
|
||||
ao2_t_ref(dialogs, -1, "unref the dialogs table");
|
||||
|
Reference in New Issue
Block a user