]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
See if SA_RESTART signals will interrupt select().
authorDarren Tucker <dtucker@dtucker.net>
Fri, 1 May 2020 05:09:26 +0000 (15:09 +1000)
committerDarren Tucker <dtucker@dtucker.net>
Fri, 1 May 2020 05:09:26 +0000 (15:09 +1000)
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
misc.c

index 8adfcb347e786ef84a3d54b78268d24f13b20632..e696ac7510fe01beac98c48f3af3cd31858dbd7e 100644 (file)
@@ -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 <sys/select.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <signal.h>
+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 5065072269791e40c17b85db3ffe5224033b6ddd..554ceb0b17d10da4dcfaeb78e4058b7c3bdbf34b 100644 (file)
--- 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;