Subject: | Reaper problem (?) [patch provided] |
Module: Schedule-Cron 0.05
Perl: 5.6.1
OS: Linux 2.4.18 (RH 7.3)
Apply patch with: patch -p0 < schedule-cron-lb.patch
Hope it helps.
When run from a process (e.g. Proc::Simple) that has installed its own signal handler for $SIG{CHLD} zombies are generated whenever a dispatched
process terminates.
My patch borrows the reaper code from Proc::Simple (a simplified one) and installs a new $SIG{CHLD} only when Schedule::Cron->run is executed. It also keeps track on the spawned children trying to reap them individually without blocking. This is useful if there is a long running task (say task A). Using the original reaper, if a second task B, started after task A, finishes before it, a third task C will have to wait. This causes task C to start its activity in an unpredictable moment.
diff -ruN Schedule-Cron-0.05/Cron.pm Schedule-Cron-0.05-lb/Cron.pm
--- Schedule-Cron-0.05/Cron.pm Wed Jul 5 10:02:26 2000
+++ Schedule-Cron-0.05-lb/Cron.pm Mon Jan 12 19:23:24 2004
@@ -71,6 +71,7 @@
use Time::ParseDate;
use Data::Dumper;
+use POSIX ":sys_wait_h";
use strict;
use vars qw($VERSION $DEBUG);
@@ -79,6 +80,7 @@
$VERSION = q$Revision: 1.5 $ =~ /(\d+)\.(\d+)/ && sprintf("%d.%02d",$1-1,$2 );
my $DEBUG = 0;
+my %STARTEDCHILD = ();
my @WDAYS = qw(
Sunday
@@ -116,13 +118,14 @@
);
sub REAPER {
- my $waitedpid = 0;
- while($waitedpid != -1) {
- $waitedpid = wait;
- }
- $SIG{CHLD} = \&REAPER;
+ foreach my $pid (keys %STARTEDCHILD) {
+ if (my $res = waitpid($pid, WNOHANG) > 0) {
+ # We reaped a truly running process
+ delete $STARTEDCHILD{$pid};
+ }
+ }
}
-$SIG{CHLD} = \&REAPER;
+
=item $cron = new Schedule::Cron($dispatcher,[extra args])
@@ -444,6 +447,9 @@
$self->build_initial_queue;
die "Nothing in schedule queue" unless @{$self->{queue}};
+ $SIG{'CHLD'} = \&REAPER;
+
+
my $mainloop = sub {
while (42) {
my ($index,$time) = @{shift @{$self->{queue}}};
@@ -672,7 +678,9 @@
if ($pid = fork) {
# Parent
- return;
+ # Register PID
+ $STARTEDCHILD{$pid} = 1;
+ return;
} else {
# Child
my $dispatch = $self->{dispatcher};