summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Down <chris@chrisdown.name>2023-01-28 12:53:48 +0100
committerRafael Marçalo <raroma09@gmail.com>2023-01-31 20:22:12 +0000
commit65d56e8b54931c93cb656257e1f639e47b0d20d8 (patch)
tree71efba73c1c80366e4e8a34ba9f476e1581cc6a3
parent535e20c8daa7b2e7131a5b88d1d776987df6cd12 (diff)
Use sigaction(SA_NOCLDWAIT) for SIGCHLD handling
signal() semantics are pretty unclearly specified. For example, depending on OS kernel and libc, the handler may be returned to SIG_DFL (hence the inner call to read the signal handler). Moving to sigaction() means the behaviour is consistently defined. Using SA_NOCLDWAIT also allows us to avoid calling the non-reentrant function die() in the handler. Some addditional notes for archival purposes: * NRK pointed out errno of waitpid could also theoretically get clobbered. * The original patch was iterated on and modified by NRK and Hiltjo: * SIG_DFL was changed to SIG_IGN, this is required, atleast on older systems such as tested on Slackware 11. * signals are not blocked using sigprocmask, because in theory it would briefly for example also ignore a SIGTERM signal. It is OK if waitpid() is (in theory interrupted). POSIX reference: "Consequences of Process Termination": https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html#tag_16_01_03_01
-rw-r--r--dwm.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/dwm.c b/dwm.c
index a9d04b9..745c898 100644
--- a/dwm.c
+++ b/dwm.c
@@ -220,7 +220,6 @@ static void setmfact(const Arg *arg);
static void setup(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
-static void sigchld(int unused);
static void sighup(int unused);
static void sigterm(int unused);
static void spawn(const Arg *arg);
@@ -1711,9 +1710,16 @@ setup(void)
int i;
XSetWindowAttributes wa;
Atom utf8string;
+ struct sigaction sa;
- /* clean up any zombies immediately */
- sigchld(0);
+ /* do not transform children into zombies when they terminate */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
+
+ /* clean up any zombies (inherited from .xinitrc etc) immediately */
+ while (waitpid(-1, NULL, WNOHANG) > 0);
signal(SIGHUP, sighup);
signal(SIGTERM, sigterm);
@@ -1810,14 +1816,6 @@ showhide(Client *c)
}
void
-sigchld(int unused)
-{
- if (signal(SIGCHLD, sigchld) == SIG_ERR)
- die("can't install SIGCHLD handler:");
- while (0 < waitpid(-1, NULL, WNOHANG));
-}
-
-void
sighup(int unused)
{
Arg a = {.i = 1};