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

Hi monks, I ran into a signal handler issue when writing a client server app. The client forks a process for each server to be queried and reaps the children with this signal handler upon receiving CHLD:
sub cleanup { while ((my $kpid = waitpid(-1,WNOHANG)) > 0) { delete($kids{$kpid}); $kidcount--; } }
This works fine. But lets say out of n children, m are sleeping waiting on network traffic from the server. The parent process sends USR1 signal to each one of those m children every 10 secs of uninterrupted sleep:
while ( $kidcount > 0) { my $secs = sleep 10; my $finishCount = $hostsfile->getCount - $kidcount; if ($secs == 10) { if ($outfile and $errfile) { print STDERR "Output is being logged into $outfile\n"; print STDERR "Errors are being logged into $errfile\n"; } print STDERR "\nFinished $finishCount hosts. following ($kidco +unt)hosts remaining:\n"; while ( my ($k, $v) = each %kids) { kill "USR1", $k; print STDERR "$v\n"; } print STDERR "\n"; } }
The signal handler is as follows:
sub killMyself { if ($waitcount > 6) { print STDERR "$serverName ERROR:: The host is hosed\n"; exit; } $waitcount++; }
So upon 7 USR1 signals, the kid should exit out. This works perfectly fine with perl 5.8.4 running on a 64 bit linux(redhat 4) machine. But on a 32 bit linux(redhat 4) machine with perl 5.8.0 or a solaris 8 machine running the same perl this is what happens: The first time USR1 signal is received, the child executes the handler and everything is good. On the second time, the child just terminates. What am i doing wrong? I hope the code provided above and the explanation is clear. thanks in advance -yogi

Replies are listed 'Best First'.
Re: signal handler question
by andyford (Curate) on Dec 08, 2006 at 20:19 UTC

    I would not mess with the signal handling part. You're reinventing a particularly thorny wheel.
    Oops sorry for the mixed metaphor.
    I would recommend using a module like Parallel::Forkmanager and let the children timeout on their own internally.

    Update: formatting

    non-Perl: Andy Ford

Re: signal handler question (podozen/2)
by tye (Sage) on Dec 09, 2006 at 00:06 UTC

    There are different schemes for how signals and handlers behave. I think some of those schemes require that the signal handler redeclare itself as handling the signal:

    sub killMyself { my( $sig )= @_; $SIG{$sig}= \&killMyself; if ($waitcoun­t > 6) { print STDERR "$serverNa­me ERROR:: The host is hosed\n"; exit; } $waitcount­++; }

    But I'm not certain. Could be worth a try until a better answer comes along?

    - tye        

Re: signal handler question
by chrism01 (Friar) on Dec 11, 2006 at 01:21 UTC
    Just FYI, in my old version of the Perl Cookbook, Recipe 16.17 discusses this pt in detail, with examples and says that some systems do require you to re-install the sig handler in the sub.
    It also says you check for 'reliable signals' with

    use Config;
    print "Hurrah!\n" if $config{d_sigaction};

    Well worth reading.