http://www.perlmonks.org?node_id=42793

jhanna has asked for the wisdom of the Perl Monks concerning the following question:

I'm working on a spam filtering smtp http://perl-esmtpd.sourceforge.net in perl. The server mode works great. The inet version always leaves a zombie on FreeBSD when run by stunnel. I've tried $SIG{CHLD}='IGNORE' and I've tried with the standard REAPER and I've tried without a SIG{CHLD}, I've tried DEFAULT...

How can I keep these zombies from remaining undead!

(Stunnel http://www.stunnel.org is a ssl wrapper for inet type programs and more.)

novice,
john

  • Comment on nite of the living dead: perl and stunnel make zombies

Replies are listed 'Best First'.
Re: nite of the living dead: perl and stunnel make zombies
by Fastolfe (Vicar) on Nov 22, 2000 at 03:08 UTC
    Setting $SIG{CHLD} to 'IGNORE' will certainly allow zombies to be created. The reason they're there is because the parent has not (through omission or inability) called wait (or waitpid) to acknowledge the child's death. Something simple like this should work:
    $SIG{CHLD} = sub { wait };
    This needs to be set before (execution-wise) any fork is done.

    Update: I am working under the assumption that your description of "a zombie" being left behind was accurate. If there's a chance that you'll get multiple child deaths rapidly, merlyn explains below that this is not sufficient. Regardless, the "standard" REAPER function that you said you were using should have worked in the first place. I am suspicious that $SIG{CHLD} isn't being declared in the correct place or is being localized unnecessarily.

      That's neither necessary nor sufficient.

      The problem is that you might get one SIGCHLD even though more than one child has gone belly up, and thus you aren't waiting long enough.

      Either use a double-fork solution (so the kids are effectively orphaned grandkids who become adopted by process #1), or a waitpid loop until there are no more kids to reap at opportune times in your algorithm.

      -- Randal L. Schwartz, Perl hacker

        One method to do the latter:
        use POSIX ":sys_wait_h"; SIG{CHLD} = \&REAPER; sub REAPER { 1 while (waitpid(-1,&WNOHANG) != -1); $SIG{CHLD} = \&REAPER; }
        On a somewhat off-topic note, what version of the perldocs (like this one) are the ones on PerlMonks? 5.6's waitpid docs have an example of exactly this, whereas 'tis missing on PerlMonks..
        perl -e 'print "Just use $^X$\"$]!$/"'

      That actually depends on what operating system you are using. System-V-based Unix let you say $SIG{CHLD}='IGNORE' when you mean "I don't care about watching my children die so just clean up the mess and don't bother me" which means you get no zombies. BSD-ish Unix doesn't.

              - tye (but my friends call me "Tye")
Re: nite of the living dead: perl and stunnel make zombies
by cephas (Pilgrim) on Nov 22, 2000 at 04:59 UTC
    I'm not sure what you consider a standard REAPER function, but this should do the trick:


    (untested for syntax errors or other nonsense)
    $SIG{'CHLD'} = \&REAPER; sub REAPER { 1 until (waitpid(-1,WNOHANG) == -1); #Loop in case we have #multiple children $SIG{'CHLD'} = \&REAPER; #reinstall the signal #handler }


    cephas
      Guys, Thanks for the comments... I'm wondering if the issue is that PERL and it's system(@_) call are the CHLDren and grandCHLDren of Stunnel... does that matter? j