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 */
{
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.
/*! \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;
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)) {
}
/* 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.
/* 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;
struct sip_threadinfo *th;
struct ast_context *con;
struct ao2_iterator i;
+ int wait_count;
network_change_event_unsubscribe();
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);
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);
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");