From 6c6072ba8b079e6f5caa38b011a6f4570c14ed38 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 1 May 2020 15:09:26 +1000 Subject: See if SA_RESTART signals will interrupt select(). On some platforms (at least older HP-UXes such as 11.11, possibly others) setting SA_RESTART on signal handers will cause it to not interrupt select(), at least for calls that do not specify a timeout. Try to detect this and if found, don't use SA_RESTART. POSIX says "If SA_RESTART has been set for the interrupting signal, it is implementation-dependent whether select() restarts or returns with [EINTR]" so this behaviour is within spec. --- configure.ac | 37 +++++++++++++++++++++++++++++++++++++ misc.c | 2 ++ 2 files changed, 39 insertions(+) diff --git a/configure.ac b/configure.ac index 8adfcb347..e696ac751 100644 --- a/configure.ac +++ b/configure.ac @@ -2500,6 +2500,43 @@ static void sighandler(int sig) { _exit(1); } ) fi +AC_MSG_CHECKING([if SA_RESTARTed signals interrupt select()]) +AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ +#ifdef HAVE_SYS_SELECT +# include +#endif +#include +#include +#include +#include +static void sighandler(int sig) { } + ]], [[ + int r; + pid_t pid; + struct sigaction sa; + + sa.sa_handler = sighandler; + sa.sa_flags = SA_RESTART; + (void)sigaction(SIGTERM, &sa, NULL); + if ((pid = fork()) == 0) { /* child */ + sleep(1); + kill(getppid(), SIGTERM); + sleep(1); + kill(getppid(), SIGKILL); + exit(0); + } else { /* parent */ + r = select(0, NULL, NULL, NULL, NULL); + } + exit(r == -1 ? 0 : 1); + ]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_DEFINE([NO_SA_RESTART], [1], + [SA_RESTARTed signals do no interrupt select])], + [AC_MSG_WARN([cross compiling: assuming yes])] +) + AC_CHECK_FUNCS([getpgrp],[ AC_MSG_CHECKING([if getpgrp accepts zero args]) AC_COMPILE_IFELSE( diff --git a/misc.c b/misc.c index 506507226..554ceb0b1 100644 --- a/misc.c +++ b/misc.c @@ -2258,8 +2258,10 @@ ssh_signal(int signum, sshsig_t handler) memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; sigfillset(&sa.sa_mask); +#if defined(SA_RESTART) && !defined(NO_SA_RESTART) if (signum != SIGALRM) sa.sa_flags = SA_RESTART; +#endif if (sigaction(signum, &sa, &osa) == -1) { debug3("sigaction(%s): %s", strsignal(signum), strerror(errno)); return SIG_ERR; -- cgit v1.2.3