Index: main/asterisk.c =================================================================== --- main/asterisk.c (revision 156248) +++ main/asterisk.c (working copy) @@ -3277,6 +3277,10 @@ sigaddset(&sigs, SIGWINCH); pthread_sigmask(SIG_BLOCK, &sigs, NULL); signal(SIGURG, urg_handler); + /* For the cases when we're using a socket-based system call, interrupting + * it requires using a different signal, one that is not intended for use + * with sockets. Hence, USR2. */ + signal(SIGUSR2, urg_handler); signal(SIGINT, __quit_handler); signal(SIGTERM, __quit_handler); signal(SIGHUP, hup_handler); Index: main/tcptls.c =================================================================== --- main/tcptls.c (revision 156248) +++ main/tcptls.c (working copy) @@ -42,7 +42,40 @@ #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_sigusr2 { + pthread_t tid; + int schedid; +}; + +static void *do_monitor(void *data) +{ + int res; + /* For debugging */ + int runq = 0, events = 0; + for (;;) { + if ((res = ast_sched_wait(sched)) != 0) { + poll(NULL, 0, res == -1 ? 10000 : res); + } + events += ast_sched_runq(sched); + runq++; + } + return NULL; +} + +static int send_sigusr2(const void *vid) +{ + struct send_sigusr2 *ssu = (void *)vid; + /* Can't cancel a connect(2) with an URG, use USR2 */ + pthread_kill(ssu->tid, SIGUSR2); + 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 +262,7 @@ { int flags; struct ast_tcptls_session_instance *ser = NULL; + struct send_sigusr2 ssu = { .schedid = -1, .tid = pthread_self() }; /* Do nothing if nothing has changed */ if(!memcmp(&desc->oldsin, &desc->sin, sizeof(desc->oldsin))) { @@ -248,13 +282,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_sigusr2, &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; Index: res/res_agi.c =================================================================== --- res/res_agi.c (revision 156248) +++ res/res_agi.c (working copy) @@ -696,6 +696,7 @@ signal(SIGCHLD, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGURG, SIG_DFL); + signal(SIGUSR2, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGXFSZ, SIG_DFL);