st

simple terminal
git clone git://git.suckless.org/st
Log | Files | Refs | README | LICENSE

commit 04ce0d643ed17793803e8516f4c9a5b13b93c400
parent 688f70add0d1da8a416bf7df763328d694a24a3a
Author: Avro <avro@disroot.org>
Date:   Mon, 29 Jun 2026 14:26:34 +0000

fix async-unsafe error paths in sigchld()

die() calls vfprintf(3) and exit(3), which are not
async-signal-safe.  If SIGCHLD is handled while exiting, this
can make st hang or crash.

Commit d6ea0a1 replaced exit(3) by _exit(2) in sigchld()
but the error paths still call die().  Fix that by using
_exit(2) there as well.

Diffstat:
Mst.c | 21+++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/st.c b/st.c @@ -712,19 +712,24 @@ execsh(char *cmd, char **args) void sigchld(int a) { - int stat; + int stat, olderrno; pid_t p; - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); + olderrno = errno; + do { + p = waitpid(pid, &stat, WNOHANG); + } while (p < 0 && errno == EINTR); - if (pid != p) + if (p < 0) + _exit(1); + + if (pid != p) { + errno = olderrno; return; + } - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); + if ((WIFEXITED(stat) && WEXITSTATUS(stat)) || WIFSIGNALED(stat)) + _exit(1); _exit(0); }