-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sleep 10 | read
hangs interactive shell after ^Z
#750
Comments
Thank you for the pointers in #763 (comment), @McDutchie! I'd say it is a different bug than #750, tough. The following line seems to cause the problem: ksh/src/cmd/ksh93/bltins/sleep.c Line 143 in 9ea4e32
This conversion is actually not valid in C as shown by this experiment #include <math.h>
#include <stdio.h>
int main(void) {
double d = INFINITY;
printf("double = %f, int = %d\n", d, (int) d);
} $ clang -fsanitize=undefined inf.c && ./a.out
inf.c:6:42: runtime error: inf is outside the range of representable values of type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior inf.c:6:42
double = inf, int = 2147483647 and the C99 standard itself:
|
Thanks for that. Looks like Here is a patch that should fix undefined behaviour and implement diff --git a/src/cmd/ksh93/bltins/sleep.c b/src/cmd/ksh93/bltins/sleep.c
index e849ef44b..a899e8279 100644
--- a/src/cmd/ksh93/bltins/sleep.c
+++ b/src/cmd/ksh93/bltins/sleep.c
@@ -29,6 +29,7 @@
#include <error.h>
#include <errno.h>
#include <tmx.h>
+#include <ast_float.h>
#include "builtins.h"
#include "FEATURE/time"
#include "FEATURE/poll"
@@ -140,9 +141,27 @@ skip:
*/
void sh_delay(double t, int sflag)
{
- int n = (int)t;
+ uint32_t n;
Tv_t ts, tx;
+#if _lib_fpclassify
+ switch (fpclassify(t))
+ {
+ case FP_NAN:
+ errormsg(SH_DICT,ERROR_exit(1),e_number,"NaN");
+ UNREACHABLE();
+ case FP_INFINITE:
+ ts.tv_sec = 0xFFFFFFFF; /* uint32_t max */
+ ts.tv_nsec = 0;
+ while (1)
+ {
+ tvsleep(&ts, NULL);
+ if ((sh.trapnote & (SH_SIGSET | SH_SIGTRAP)) || sflag)
+ return;
+ }
+ }
+#endif
+ n = (uint32_t)t;
ts.tv_sec = n;
ts.tv_nsec = 1000000000 * (t - (double)n);
while(tvsleep(&ts, &tx) < 0) |
Thank you, @McDutchie! I confirm that your patch fixes the issue described in #763 (comment). $ strace arch/linux.arm64-64/bin/ksh -c 'sleep inf'
...
rt_sigaction(SIGWINCH, {sa_handler=0x44ee5c, sa_mask=[], sa_flags=SA_INTERRUPT}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGALRM, {sa_handler=0x44ee5c, sa_mask=[], sa_flags=SA_INTERRUPT}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=4294967295, tv_nsec=0}, |
The 'sleep' built-in takes a floating-point duration value, so passing the special float values Inf (infinite) and NaN (not a number) is also possible. However, the code did not handle these values specially, resulting in undefined behaviour when the whole and fractional parts were typecast to integers in sh_delay(). src/cmd/ksh93/bltins/sleep.c: - b_sleep(): Trigger a "bad number" error if NaN is passed. - sh_delay(): Handle Inf separately with an infinite loop, which can be interrupted as appropriate by a signal. Discussion: #750 (comment)
The 'sleep' built-in takes a floating-point duration value, so passing the special float values Inf (infinite) and NaN (not a number) is also possible. However, the code did not handle these values specially, resulting in undefined behaviour when the whole and fractional parts were typecast to integers in sh_delay(). src/cmd/ksh93/bltins/sleep.c: - b_sleep(): Trigger a "bad number" error if NaN is passed. - sh_delay(): Handle Inf separately with an infinite loop, which can be interrupted as appropriate by a signal. Discussion: #750 (comment)
Found on comp.unix.shell:
The text was updated successfully, but these errors were encountered: