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

hi smart guys, i've written a simple perl server running under sunos5.8 as part of a bigger project. this server is set up to fork a child for each request. the server has to interact with a mysql db, so i used the standard dbi module to query my data source. i've modified a bit the standard reaping code i found in the perlipc manpage to suit my needs but it seems that some SIGCHLDs are just ignored, letting orphans children wandering about... soon, i realized the process table fills up with defunct processes over a relatively short running time, causing hell of trouble! i'm almost sure the problem resides in the reaping code. the number of requests per sec is very high, so i suppose some SIGCHLD handlings overlap. any ideas? thanks in advance...
my $waitedpid = 0; my %dbh_pool = (); sub REAPER { $waitedpid = waitpid(-1,WNOHANG); $SIG{CHLD} = \&REAPER; if (defined $waitedpid && $dbh_pool{$waitedpid}{"Active"}) { $dbh_pool{$waitedpid}->disconnect; delete $dbh_pool{$waitedpid}; } } $SIG{CHLD} = \&REAPER;

Replies are listed 'Best First'.
Re: reaping defunct children
by autark (Friar) on Feb 16, 2001 at 15:10 UTC
    If your process gets two or more SIGCHLD signals before being scheduled, only one signal will arrive. This because the kernel keeps track of the signals to your process in a bit vector, one bit per uniq signal. The solution is to loop, like this:
    sub REAPER { my $pid; while(( $pid = waitpid(-1, WNOHANG)) > 0) { # Do stuff } $SIG{CHLD} = \&REAPER; }
    Autark.
Re (tilly) 1: reaping defunct children
by tilly (Archbishop) on Feb 16, 2001 at 17:22 UTC
    Note that signal handlers in Perl are notoriously unreliable. I strongly recommend that you don't use them and instead just call waitpid regularly.

    On a more positive note, for a network server you may find the POE module very useful for simplifying your life.

Re: reaping defunct children
by mikfire (Deacon) on Feb 16, 2001 at 20:59 UTC
    Do not re-install the signal handler. That one little line of code has caused me a fair amount of pain in the past, on Solaris as a matter of fact. According to perlipc:
      But that will be problematic for the more complicated
      handlers that need to reinstall themselves.  Because Perl's
      signal mechanism is currently based on the signal(3)
      function from the C library, you may sometimes be so
      misfortunate as to run on systems where that function is
      "broken", that is, it behaves in the old unreliable SysV way
    
    ( the emphasis is mine ). Most systems people work on today are not broken. I know Solaris is at least one of them. FreeBSD is another. I would imagine Linux isn't either, but don't know for certain because I don't work on Linux boxen.

    Follow tilly's advice.

    mikfire