iUse sigaction(SA_NOCLDWAIT) for SIGCHLD handling - dwm - dynamic window manager Err parazyd.org 70 hgit clone https://git.parazyd.org/dwm URL:https://git.parazyd.org/dwm parazyd.org 70 1Log /git/dwm/log.gph parazyd.org 70 1Files /git/dwm/files.gph parazyd.org 70 1Refs /git/dwm/refs.gph parazyd.org 70 1README /git/dwm/file/README.gph parazyd.org 70 1LICENSE /git/dwm/file/LICENSE.gph parazyd.org 70 i--- Err parazyd.org 70 1commit 712d6639ff8e863560328131bbb92b248dc9cde7 /git/dwm/commit/712d6639ff8e863560328131bbb92b248dc9cde7.gph parazyd.org 70 1parent 89f9905714c1c1b2e8b09986dfbeca15b68d8af8 /git/dwm/commit/89f9905714c1c1b2e8b09986dfbeca15b68d8af8.gph parazyd.org 70 hAuthor: Chris Down URL:mailto:chris@chrisdown.name parazyd.org 70 iDate: Sat, 28 Jan 2023 12:53:48 +0100 Err parazyd.org 70 i Err parazyd.org 70 iUse sigaction(SA_NOCLDWAIT) for SIGCHLD handling Err parazyd.org 70 i Err parazyd.org 70 isignal() semantics are pretty unclearly specified. For example, depending on OS Err parazyd.org 70 ikernel and libc, the handler may be returned to SIG_DFL (hence the inner call Err parazyd.org 70 ito read the signal handler). Moving to sigaction() means the behaviour is Err parazyd.org 70 iconsistently defined. Err parazyd.org 70 i Err parazyd.org 70 iUsing SA_NOCLDWAIT also allows us to avoid calling the non-reentrant function Err parazyd.org 70 idie() in the handler. Err parazyd.org 70 i Err parazyd.org 70 iSome addditional notes for archival purposes: Err parazyd.org 70 i Err parazyd.org 70 i* NRK pointed out errno of waitpid could also theoretically get clobbered. Err parazyd.org 70 i* The original patch was iterated on and modified by NRK and Hiltjo: Err parazyd.org 70 i * SIG_DFL was changed to SIG_IGN, this is required, atleast on older systems Err parazyd.org 70 i such as tested on Slackware 11. Err parazyd.org 70 i * signals are not blocked using sigprocmask, because in theory it would Err parazyd.org 70 i briefly for example also ignore a SIGTERM signal. It is OK if waitpid() is (in Err parazyd.org 70 i theory interrupted). Err parazyd.org 70 i Err parazyd.org 70 iPOSIX reference: Err parazyd.org 70 i"Consequences of Process Termination": Err parazyd.org 70 ihttps://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html#tag_16_01_03_01 Err parazyd.org 70 i Err parazyd.org 70 iDiffstat: Err parazyd.org 70 i M dwm.c | 20 +++++++++----------- Err parazyd.org 70 i Err parazyd.org 70 i1 file changed, 9 insertions(+), 11 deletions(-) Err parazyd.org 70 i--- Err parazyd.org 70 1diff --git a/dwm.c b/dwm.c /git/dwm/file/dwm.c.gph parazyd.org 70 i@@ -205,7 +205,6 @@ static void setmfact(const Arg *arg); Err parazyd.org 70 i static void setup(void); Err parazyd.org 70 i static void seturgent(Client *c, int urg); Err parazyd.org 70 i static void showhide(Client *c); Err parazyd.org 70 i-static void sigchld(int unused); Err parazyd.org 70 i static void spawn(const Arg *arg); Err parazyd.org 70 i static void tag(const Arg *arg); Err parazyd.org 70 i static void tagmon(const Arg *arg); Err parazyd.org 70 i@@ -1543,9 +1542,16 @@ setup(void) Err parazyd.org 70 i int i; Err parazyd.org 70 i XSetWindowAttributes wa; Err parazyd.org 70 i Atom utf8string; Err parazyd.org 70 i+ struct sigaction sa; Err parazyd.org 70 i Err parazyd.org 70 i- /* clean up any zombies immediately */ Err parazyd.org 70 i- sigchld(0); Err parazyd.org 70 i+ /* do not transform children into zombies when they terminate */ Err parazyd.org 70 i+ sigemptyset(&sa.sa_mask); Err parazyd.org 70 i+ sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; Err parazyd.org 70 i+ sa.sa_handler = SIG_IGN; Err parazyd.org 70 i+ sigaction(SIGCHLD, &sa, NULL); Err parazyd.org 70 i+ Err parazyd.org 70 i+ /* clean up any zombies (inherited from .xinitrc etc) immediately */ Err parazyd.org 70 i+ while (waitpid(-1, NULL, WNOHANG) > 0); Err parazyd.org 70 i Err parazyd.org 70 i /* init screen */ Err parazyd.org 70 i screen = DefaultScreen(dpy); Err parazyd.org 70 i@@ -1639,14 +1645,6 @@ showhide(Client *c) Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i void Err parazyd.org 70 i-sigchld(int unused) Err parazyd.org 70 i-{ Err parazyd.org 70 i- if (signal(SIGCHLD, sigchld) == SIG_ERR) Err parazyd.org 70 i- die("can't install SIGCHLD handler:"); Err parazyd.org 70 i- while (0 < waitpid(-1, NULL, WNOHANG)); Err parazyd.org 70 i-} Err parazyd.org 70 i- Err parazyd.org 70 i-void Err parazyd.org 70 i spawn(const Arg *arg) Err parazyd.org 70 i { Err parazyd.org 70 i if (arg->v == dmenucmd) Err parazyd.org 70 .