The sleep builtin currently doesn't do much in the way of signal management, so for example it will return on SIGWINCH, which I think most users will be particularly surprised by the first time they notice a sleep ending early due to a window resize.
I looked at adding more signal handling to the current select-based implementation but then realized it would be a lot easier to just use nanosleep(2). Both select() and nanosleep() first appear in 1997's XSH Issue 5 so I don't know if we need to worry much about systems without it. (The patch leaves the select/pselect code as fallback though). --- diff --git a/config.h.in b/config.h.in index c2750a2a..1b6a1853 100644 --- a/config.h.in +++ b/config.h.in @@ -771,6 +771,9 @@ /* Define if you have the mkstemp function. */ #undef HAVE_MKSTEMP +/* Define if you have the nonosleep function. */ +#undef HAVE_NANOSLEEP + /* Define if you have the pathconf function. */ #undef HAVE_PATHCONF diff --git a/configure.ac b/configure.ac index 29f50438..de7d693c 100644 --- a/configure.ac +++ b/configure.ac @@ -850,9 +850,9 @@ AC_REPLACE_FUNCS(rename) dnl checks for c library functions AC_CHECK_FUNCS(bcopy bzero clock_gettime confstr faccessat fnmatch \ getaddrinfo gethostbyname getservbyname getservent inet_aton \ - imaxdiv memmove pathconf putenv raise random regcomp regexec \ - setenv setlinebuf setlocale setvbuf siginterrupt strchr \ - sysconf syslog tcgetattr times ttyname tzset unsetenv) + imaxdiv memmove nanosleep pathconf putenv raise random regcomp \ + regexec setenv setlinebuf setlocale setvbuf siginterrupt \ + strchr sysconf syslog tcgetattr times ttyname tzset unsetenv) AC_CHECK_FUNCS(vasprintf asprintf) AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit) diff --git a/lib/sh/ufuncs.c b/lib/sh/ufuncs.c index 247224d6..b3894450 100644 --- a/lib/sh/ufuncs.c +++ b/lib/sh/ufuncs.c @@ -82,7 +82,26 @@ falarm (unsigned int secs, unsigned int usecs) /* A version of sleep using fractional seconds and select. I'd like to use `usleep', but it's already taken */ -#if defined (HAVE_TIMEVAL) && (defined (HAVE_SELECT) || defined (HAVE_PSELECT)) +#if defined (HAVE_NANOSLEEP) +int +fsleep(unsigned int sec, unsigned int usec) +{ + int r; + struct timespec req, rem; + + req.tv_sec = sec; + req.tv_nsec = usec * 1000; + + for (;;) + { + QUIT; + r = nanosleep (&req, &rem); + if (r == 0 || errno != EINTR) + return r; + req = rem; + } +} +#elif defined (HAVE_TIMEVAL) && (defined (HAVE_SELECT) || defined (HAVE_PSELECT)) int fsleep(unsigned int sec, unsigned int usec) {
From a33289b218028b6d72966d8253646d6f174e09a5 Mon Sep 17 00:00:00 2001 From: Grisha Levit <grishalevit@gmail.com> Date: Thu, 29 Jun 2023 21:55:05 -0400 Subject: [PATCH] fsleep: use nanosleep, handle signals --- config.h.in | 3 +++ configure.ac | 6 +++--- lib/sh/ufuncs.c | 21 ++++++++++++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/config.h.in b/config.h.in index c2750a2a..1b6a1853 100644 --- a/config.h.in +++ b/config.h.in @@ -771,6 +771,9 @@ /* Define if you have the mkstemp function. */ #undef HAVE_MKSTEMP +/* Define if you have the nonosleep function. */ +#undef HAVE_NANOSLEEP + /* Define if you have the pathconf function. */ #undef HAVE_PATHCONF diff --git a/configure.ac b/configure.ac index 29f50438..de7d693c 100644 --- a/configure.ac +++ b/configure.ac @@ -850,9 +850,9 @@ AC_REPLACE_FUNCS(rename) dnl checks for c library functions AC_CHECK_FUNCS(bcopy bzero clock_gettime confstr faccessat fnmatch \ getaddrinfo gethostbyname getservbyname getservent inet_aton \ - imaxdiv memmove pathconf putenv raise random regcomp regexec \ - setenv setlinebuf setlocale setvbuf siginterrupt strchr \ - sysconf syslog tcgetattr times ttyname tzset unsetenv) + imaxdiv memmove nanosleep pathconf putenv raise random regcomp \ + regexec setenv setlinebuf setlocale setvbuf siginterrupt \ + strchr sysconf syslog tcgetattr times ttyname tzset unsetenv) AC_CHECK_FUNCS(vasprintf asprintf) AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit) diff --git a/lib/sh/ufuncs.c b/lib/sh/ufuncs.c index 247224d6..b3894450 100644 --- a/lib/sh/ufuncs.c +++ b/lib/sh/ufuncs.c @@ -82,7 +82,26 @@ falarm (unsigned int secs, unsigned int usecs) /* A version of sleep using fractional seconds and select. I'd like to use `usleep', but it's already taken */ -#if defined (HAVE_TIMEVAL) && (defined (HAVE_SELECT) || defined (HAVE_PSELECT)) +#if defined (HAVE_NANOSLEEP) +int +fsleep(unsigned int sec, unsigned int usec) +{ + int r; + struct timespec req, rem; + + req.tv_sec = sec; + req.tv_nsec = usec * 1000; + + for (;;) + { + QUIT; + r = nanosleep (&req, &rem); + if (r == 0 || errno != EINTR) + return r; + req = rem; + } +} +#elif defined (HAVE_TIMEVAL) && (defined (HAVE_SELECT) || defined (HAVE_PSELECT)) int fsleep(unsigned int sec, unsigned int usec) { -- 2.41.0