Subject: bug#32452: 26.1; gnutls_try_handshake maxes out cpu retrying when server is a bit busy

From: Paul Eggert <[email-masked]>
Date: Fri, 25 Feb 2022 12:41:08 -0800

On 2/24/22 18:27, Lars Ingebrigtsen wrote:

> But autogen.sh fails:
> 
> Running 'autoreconf -fi -I m4' ...
> configure.ac:6060: warning: gl_FUNC_SELECT is m4_require'd but not m4_defun'd

This is because Gnulib's 'nanosleep' module depended on the 'select' 
module, but Emacs's admin/merge-gnulib avoids the 'select' module 
(because Emacs relies on pselect instead and has its own MS-DOS pselect 
substitute).

Gnulib's nanosleep appears to use select only for old Unixish platforms 
that were relevant in 2000 but aren't practical porting targets any 
more. So I installed into Gnulib the attached patch to simplify Gnulib 
nanosleep by having it fall back on pselect rather than select, and to 
not bother with signal handling. This should cause your addition of 
nanosleep to admin/merge-gnulib to add only the files lib/nanosleep.c 
and m4/nanosleep.m4 (not the other, signal-related files you mentioned; 
they shouldn't be needed with Emacs).

You might also want to adopt my recent little merge-gnulib changes.

I notice that Emacs's GNUstep code calls 'select'. For completeness this 
should be 'pselect' instead, so that Emacs never calls 'select'.

From 2510ffcdcdad4e5cd20455b4891de4f5e128072a Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Fri, 25 Feb 2022 11:54:49 -0800
Subject: [PATCH] nanosleep: simplify by using pselect
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

GNU Emacs avoids Gnulib’s ‘select’ module and uses only pselect,
which it implements in a special way on MS-DOS.
Unfortunately, though, nanosleep uses ‘select’;
problem reported by Lars Ingebrigtsen (Bug#32452#74).
As far as I can tell, Gnulib nanosleep's use of
‘select’ with signals is only for ancient platforms
that Gnulib no longer cares about, so remove that use of ‘select’.
I don’t know of any platforms that still need this fallback code,
but just in case, fall back to pselect instead, while removing
signal handling that it shouldn’t be needed nowadays.
* lib/nanosleep.c: Do not include sig-handler.h, sys/time.h.
(SIGCONT, suspended, sighandler, my_usleep): Remove.
(nanosleep) [!HAVE_BUG_BIG_NANOSLEEP && !(_WIN32 && !__CYGWIN__)]:
Just call pselect.
* m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): Do not check for sys/time.h
or call gl_FUNC_SELECT.  Do not include sys/time.h or worry
about LIBSOCKET.
(gl_PREREQ_NANOSLEEP): Remove as it’s no longer needed.
All uses removed.
* modules/nanosleep (Depends-on): Add pselect.
Remove select, sigaction, sys_time.
---
 ChangeLog         | 25 +++++++++++++
 lib/nanosleep.c   | 89 +++--------------------------------------------
 m4/nanosleep.m4   | 24 +------------
 modules/nanosleep |  7 +---
 4 files changed, 31 insertions(+), 114 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3499d066e4..49a1e6a168 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2022-02-25  Paul Eggert  <[email-masked]>
+
+	nanosleep: simplify by using pselect
+	GNU Emacs avoids Gnulib’s ‘select’ module and uses only pselect,
+	which it implements in a special way on MS-DOS.
+	Unfortunately, though, nanosleep uses ‘select’;
+	problem reported by Lars Ingebrigtsen (Bug#32452#74).
+	As far as I can tell, Gnulib nanosleep's use of
+	‘select’ with signals is only for ancient platforms
+	that Gnulib no longer cares about, so remove that use of ‘select’.
+	I don’t know of any platforms that still need this fallback code,
+	but just in case, fall back to pselect instead, while removing
+	signal handling that it shouldn’t be needed nowadays.
+	* lib/nanosleep.c: Do not include sig-handler.h, sys/time.h.
+	(SIGCONT, suspended, sighandler, my_usleep): Remove.
+	(nanosleep) [!HAVE_BUG_BIG_NANOSLEEP && !(_WIN32 && !__CYGWIN__)]:
+	Just call pselect.
+	* m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): Do not check for sys/time.h
+	or call gl_FUNC_SELECT.  Do not include sys/time.h or worry
+	about LIBSOCKET.
+	(gl_PREREQ_NANOSLEEP): Remove as it’s no longer needed.
+	All uses removed.
+	* modules/nanosleep (Depends-on): Add pselect.
+	Remove select, sigaction, sys_time.
+
 2022-02-24  Paul Eggert  <[email-masked]>
 
 	userspec: warn about '.' separator
diff --git a/lib/nanosleep.c b/lib/nanosleep.c
index 5294c646ae..446794edc0 100644
--- a/lib/nanosleep.c
+++ b/lib/nanosleep.c
@@ -23,7 +23,6 @@
 #include <time.h>
 
 #include "intprops.h"
-#include "sig-handler.h"
 #include "verify.h"
 
 #include <stdbool.h>
@@ -32,7 +31,6 @@
 #include <sys/select.h>
 #include <signal.h>
 
-#include <sys/time.h>
 #include <errno.h>
 
 #include <unistd.h>
@@ -181,45 +179,9 @@ nanosleep (const struct timespec *requested_delay,
 }
 
 #else
-/* Unix platforms lacking nanosleep. */
-
-/* Some systems (MSDOS) don't have SIGCONT.
-   Using SIGTERM here turns the signal-handling code below
-   into a no-op on such systems. */
-# ifndef SIGCONT
-#  define SIGCONT SIGTERM
-# endif
-
-static sig_atomic_t volatile suspended;
-
-/* Handle SIGCONT. */
-
-static _GL_ASYNC_SAFE void
-sighandler (int sig)
-{
-  suspended = 1;
-}
-
-/* Suspend execution for at least *TS_DELAY seconds.  */
-
-static int
-my_usleep (const struct timespec *ts_delay)
-{
-  struct timeval tv_delay;
-  tv_delay.tv_sec = ts_delay->tv_sec;
-  tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
-  if (tv_delay.tv_usec == 1000000)
-    {
-      if (tv_delay.tv_sec == TYPE_MAXIMUM (time_t))
-        tv_delay.tv_usec = 1000000 - 1; /* close enough */
-      else
-        {
-          tv_delay.tv_sec++;
-          tv_delay.tv_usec = 0;
-        }
-    }
-  return select (0, NULL, NULL, NULL, &tv_delay);
-}
+/* Other platforms lacking nanosleep.
+   It's not clear whether these are still practical porting targets.
+   For now, just fall back on pselect.  */
 
 /* Suspend execution for at least *REQUESTED_DELAY seconds.  The
    *REMAINING_DELAY part isn't implemented yet.  */
@@ -228,49 +190,6 @@ int
 nanosleep (const struct timespec *requested_delay,
            struct timespec *remaining_delay)
 {
-  static bool initialized;
-
-  if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
-    {
-      errno = EINVAL;
-      return -1;
-    }
-
-  /* set up sig handler */
-  if (! initialized)
-    {
-      struct sigaction oldact;
-
-      sigaction (SIGCONT, NULL, &oldact);
-      if (get_handler (&oldact) != SIG_IGN)
-        {
-          struct sigaction newact;
-
-          newact.sa_handler = sighandler;
-          sigemptyset (&newact.sa_mask);
-          newact.sa_flags = 0;
-          sigaction (SIGCONT, &newact, NULL);
-        }
-      initialized = true;
-    }
-
-  suspended = 0;
-
-  if (my_usleep (requested_delay) == -1)
-    {
-      if (suspended)
-        {
-          /* Calculate time remaining.  */
-          /* FIXME: the code in sleep doesn't use this, so there's no
-             rush to implement it.  */
-
-          errno = EINTR;
-        }
-      return -1;
-    }
-
-  /* FIXME: Restore sig handler?  */
-
-  return 0;
+  return pselect (0, NULL, NULL, NULL, requested_delay, NULL);
 }
 #endif
diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4
index 6a51f28e30..1964b1ea47 100644
--- a/m4/nanosleep.m4
+++ b/m4/nanosleep.m4
@@ -1,4 +1,4 @@
-# serial 40
+# serial 41
 
 dnl From Jim Meyering.
 dnl Check for the nanosleep function.
@@ -19,9 +19,6 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
  dnl Persuade glibc and Solaris <time.h> to declare nanosleep.
  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 
- AC_CHECK_HEADERS_ONCE([sys/time.h])
- AC_REQUIRE([gl_FUNC_SELECT])
-
  AC_CHECK_DECLS_ONCE([alarm])
 
  nanosleep_save_libs=$LIBS
@@ -53,9 +50,6 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
           #include <errno.h>
           #include <limits.h>
           #include <signal.h>
-          #if HAVE_SYS_TIME_H
-           #include <sys/time.h>
-          #endif
           #include <time.h>
           #include <unistd.h>
           #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
@@ -135,15 +129,6 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
            AC_DEFINE([HAVE_BUG_BIG_NANOSLEEP], [1],
              [Define to 1 if nanosleep mishandles large arguments.])
            ;;
-         *)
-           # The replacement uses select(). Add $LIBSOCKET to $LIB_NANOSLEEP.
-           for ac_lib in $LIBSOCKET; do
-             case " $LIB_NANOSLEEP " in
-               *" $ac_lib "*) ;;
-               *) LIB_NANOSLEEP="$LIB_NANOSLEEP $ac_lib";;
-             esac
-           done
-           ;;
        esac
        ;;
    esac
@@ -152,10 +137,3 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
  fi
  LIBS=$nanosleep_save_libs
 ])
-
-# Prerequisites of lib/nanosleep.c.
-AC_DEFUN([gl_PREREQ_NANOSLEEP],
-[
-  AC_CHECK_HEADERS_ONCE([sys/select.h])
-  gl_PREREQ_SIG_HANDLER_H
-])
diff --git a/modules/nanosleep b/modules/nanosleep
index 53c5dc5f7c..a8d0c76744 100644
--- a/modules/nanosleep
+++ b/modules/nanosleep
@@ -10,20 +10,15 @@ time
 extensions
 multiarch
 intprops        [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
-select          [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
-sigaction       [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
+pselect         [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
 stdbool         [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
 sys_select      [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
-sys_time        [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
 verify          [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1]
 
 configure.ac:
 gl_FUNC_NANOSLEEP
 gl_CONDITIONAL([GL_COND_OBJ_NANOSLEEP],
                [test $HAVE_NANOSLEEP = 0 || test $REPLACE_NANOSLEEP = 1])
-AM_COND_IF([GL_COND_OBJ_NANOSLEEP], [
-  gl_PREREQ_NANOSLEEP
-])
 gl_TIME_MODULE_INDICATOR([nanosleep])
 
 Makefile.am:
-- 
2.32.0