G'day halecommarachel,

"I had a simpler version of the below code working, but when I added some complexity, the signal handler for CHLD stopped reaping zombies. Here is my code now:"

Actually showing us what was working and what you added to stop it working would have been very useful. As it stands, we have no way of telling what change caused the failure.

Furthermore, cutting your code down to the absolute minimum which still reproduced your problem may have helped you to solve the problem by yourself. Even if you still couldn't solve it, we wouldn't have to wade through totally irrelevant code looking for a problem.

Your immediate problem is the position of the exit statement. You probably intended to exit only from the child process.

Here's a cut-down version of your script which (roughly) reproduces the problem you described:

#!/usr/bin/env perl -l use strict; use warnings; use autodie qw{:all}; use POSIX qw{WNOHANG}; my %children; $SIG{CHLD} = sub { local ($!, $?); my $pid = waitpid(-1, WNOHANG); return if $pid == -1; return unless defined $children{$pid}; delete $children{$pid}; print "SIG{CHLD}: PID $pid ", kill(0 => $pid) ? 'NOT ' : '', 'reap +ed.'; }; print "PARENT($$): Before multi_dir() call"; multi_dir(); sub multi_dir { for (0 .. 1) { my $pid = fork; die 'Undefined PID from fork()' unless defined $pid; if ($pid) { # parent $children{$pid} = 1; print "PARENT($$): Started child process with PID: $pid"; print "PARENT($$): ", scalar keys %children, ' child proce +sses'; } else { # child print "CHILD($$): New process started"; system 'echo PPID=$PPID PID=$$; sleep 1'; print "CHILD($$): system() finished"; } exit; # <<<=== PROBLEM HERE! } }

By moving the exit to the child code, the script no longer hangs:

sub multi_dir { ... print "CHILD($$): system() finished"; exit; # <<<=== PROBLEM FIXED! } } }

Having said that, I recommend you read what exit says about exiting from subroutines. Even if the simple fix I described above works for you now, when you next add a little more "complexiy" you may find yourself with problems again. Perhaps you could return with the child PID instead of using exit; then, if the end of &multi_dir is reached, return with zero — that way, you can test the return value of multi_dir() and exit if it's the child or continue with the main script if it's the parent. Here's an example:

... print "PARENT($$): Before multi_dir() call"; my $multi_dir_return = multi_dir(); if ($multi_dir_return) { print "CHILD($multi_dir_return): exiting"; exit; } print "PARENT($$): After multi_dir() call"; sub multi_dir { ... print "CHILD($$): system() finished"; return $$; } } return 0; }

Your code has some other (potential) problems. Here's a couple I spotted:

This:

if ($limit) { @subs = @subs[1 .. $limit]; }

would probably have been better as something closer to:

if (defined $limit and $limit > @subs) { @subs = @subs[0 .. $limit - 1]; }

And this:

while (keys %children >= $max) { }

is potentially an infinite loop. It's also repeatedly checking the condition, and doing nothing else, which is chewing up a lot CPU cycles unnecessarily. Consider adding a sleep with an alarm (see Time::HiRes for times with finer granularity than whole seconds).

-- Ken


In reply to Re: CHLD handler stopped working by kcott
in thread CHLD handler stopped working by halecommarachel

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.