diff options
author | Chris Down <chris@chrisdown.name> | 2023-01-28 12:53:48 +0100 |
---|---|---|
committer | Rafael Marçalo <raroma09@gmail.com> | 2023-01-31 20:22:12 +0000 |
commit | 65d56e8b54931c93cb656257e1f639e47b0d20d8 (patch) | |
tree | 71efba73c1c80366e4e8a34ba9f476e1581cc6a3 | |
parent | 535e20c8daa7b2e7131a5b88d1d776987df6cd12 (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.c | 20 |
1 files changed, 9 insertions, 11 deletions
@@ -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}; |