Skip to content

Commit ea42e0f

Browse files
committed
macOS: work around freeze: don't suspend 'sleep' on interactive
Steps to reproduce: 1. sleep 3 2. press Ctrl+Z before it finishes (sleep builtin is forked into its own process and suspended) 3. fg sleep should resume and terminate, but instead, the forked sleep builtin freezes, consuming 100% CPU. Only SIGKILL (kill -9) will terminate it, although it can still be suspended again. This is reproducible on (at least) macOS 12.7.6 arm64. I can also reproduce this on 93u+ 2012-08-01 and on ksh2020. It looks like this is a bug in macOS. When I compile ksh with ASan, and the forked/resumed ksh sleep process hangs, and I simulate a segfault by doing kill -s SEGV (the PID of the hanging process), then the stack trace shows that it was hanging in the nanosleep function of libsystem_c.dylib. src/cmd/ksh93/bltins/sleep.c: sh_delay(): - Make it impossible to suspend the sleep builtin on macOS by ignoring SIGTSTP. We only need to do that if we've invoked 'sleep' from the interactive prompt, i.e., if the SH_INTERACTIVE state bit is active. (See 48ba696, d11d4c7) Resolves: #814
1 parent be062b1 commit ea42e0f

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

src/cmd/ksh93/bltins/sleep.c

+14-1
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,23 @@ void sh_delay(double t, int sflag)
159159
n = (uint32_t)t;
160160
ts.tv_sec = n;
161161
ts.tv_nsec = 1000000000 * (t - (double)n);
162+
#if __APPLE__ && __MACH__
163+
/*
164+
* Bug in macOS: if sleep is invoked from the interactive command line and then suspended
165+
* (^Z), the forked ksh process freezes in the nanosleep(2) function in libsystem_c.dylib.
166+
* As a workaround, make it impossible to suspend sleep in that case, by ignoring SIGTSTP.
167+
*/
168+
if (sh_isstate(SH_INTERACTIVE))
169+
signal(SIGTSTP,SIG_IGN);
170+
#endif
162171
while(tvsleep(&ts, &tx) < 0)
163172
{
164173
if ((sh.trapnote & (SH_SIGSET | SH_SIGTRAP)) || sflag)
165-
return;
174+
break;
166175
ts = tx;
167176
}
177+
#if __APPLE__ && __MACH__
178+
if (sh_isstate(SH_INTERACTIVE))
179+
signal(SIGTSTP,SIG_DFL);
180+
#endif
168181
}

src/cmd/ksh93/include/version.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <ast_release.h>
1919
#include "git.h"
2020

21-
#define SH_RELEASE_DATE "2025-03-21" /* must be in this format for $((.sh.version)) */
21+
#define SH_RELEASE_DATE "2025-03-22" /* must be in this format for $((.sh.version)) */
2222
/*
2323
* This comment keeps SH_RELEASE_DATE a few lines away from SH_RELEASE_SVER to avoid
2424
* merge conflicts when cherry-picking dev branch commits onto a release branch.

0 commit comments

Comments
 (0)