Index: main/tcptls.c =================================================================== --- main/tcptls.c (revision 156008) +++ main/tcptls.c (working copy) @@ -42,7 +42,36 @@ #include "asterisk/strings.h" #include "asterisk/options.h" #include "asterisk/manager.h" +#include "asterisk/sched.h" + +struct sched_context *sched = NULL; +pthread_t monitor_thread = AST_PTHREADT_NULL; +struct send_sigurg { + pthread_t tid; + int schedid; +}; + +static void *do_monitor(void *data) +{ + int res; + for (;;) { + if ((res = ast_sched_wait(sched)) != 0) { + poll(NULL, 0, res); + } + ast_sched_runq(sched); + } + return NULL; +} + +static int send_sigurg(const void *vid) +{ + struct send_sigurg *ssu = (void *)vid; + pthread_kill(ssu->tid, SIGURG); + ssu->schedid = -1; + return 0; +} + /*! \brief * replacement read/write functions for SSL support. * We use wrappers rather than SSL_read/SSL_write directly so @@ -229,6 +258,7 @@ { int flags; struct ast_tcptls_session_instance *ser = NULL; + struct send_sigurg ssu = { .schedid = -1, .tid = pthread_self() }; /* Do nothing if nothing has changed */ if(!memcmp(&desc->oldsin, &desc->sin, sizeof(desc->oldsin))) { @@ -248,13 +278,31 @@ return NULL; } + if (!sched) { + sched = sched_context_create(); + } + + if (monitor_thread == AST_PTHREADT_NULL) { + if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { + ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); + monitor_thread = AST_PTHREADT_NULL; + return 0; + } + } + + /* Don't allow the connect to hang, if the TCP connection stalls. */ + ssu.schedid = ast_sched_add(sched, 2000, send_sigurg, &ssu); + pthread_kill(monitor_thread, SIGURG); + if (connect(desc->accept_fd, (const struct sockaddr *)&desc->sin, sizeof(desc->sin))) { ast_log(LOG_ERROR, "Unable to connect %s to %s:%d: %s\n", desc->name, ast_inet_ntoa(desc->sin.sin_addr), ntohs(desc->sin.sin_port), strerror(errno)); + AST_SCHED_DEL(sched, ssu.schedid); goto error; } + AST_SCHED_DEL(sched, ssu.schedid); if (!(ser = ao2_alloc(sizeof(*ser), session_instance_destructor))) goto error;