Use sigaction(SA_NOCLDWAIT) for SIGCHLD handling - dwm - dynamic window manager
 (HTM) git clone https://git.parazyd.org/dwm
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 712d6639ff8e863560328131bbb92b248dc9cde7
 (DIR) parent 89f9905714c1c1b2e8b09986dfbeca15b68d8af8
 (HTM) Author: Chris Down <chris@chrisdown.name>
       Date:   Sat, 28 Jan 2023 12:53:48 +0100
       
       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
       
       Diffstat:
         M dwm.c                               |      20 +++++++++-----------
       
       1 file changed, 9 insertions(+), 11 deletions(-)
       ---
 (DIR) diff --git a/dwm.c b/dwm.c
       @@ -205,7 +205,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 spawn(const Arg *arg);
        static void tag(const Arg *arg);
        static void tagmon(const Arg *arg);
       @@ -1543,9 +1542,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);
        
                /* init screen */
                screen = DefaultScreen(dpy);
       @@ -1639,14 +1645,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
        spawn(const Arg *arg)
        {
                if (arg->v == dmenucmd)