I would just mark the process done by zeroing the hash value.
Then at strategic points in the parent-side code I would "clean up" the list.
Here is a diff to your code that implements that change.
Mind you though, it is completely untested so there may still be gaping holes.
--- Ext/Fork.pm.00 2009-12-19 06:00:59.000000000 -0800
+++ Ext/Fork.pm 2009-12-20 15:16:22.000000000 -0800
@@ -109,6 +109,7 @@
}
while(1){
+ rfork_cleanup();
if($Ext::Fork::POOL->{children} < $Ext::Fork::POOL->{max_chil
+dren}){
last;
}
@@ -145,6 +146,7 @@
if($Ext::Fork::POOL->{has_children} && !$Ext::Fork::POOL->{nonblo
+cking}){
while(1){
+ rfork_cleanup();
last if !$Ext::Fork::POOL->{children};
if($Ext::Fork::has_thr){
rfork_usleep(500);
@@ -195,8 +197,7 @@
sub _sigchld {
while((my $p = waitpid(-1, WNOHANG)) > 0){
- delete $Ext::Fork::POOL->{cidlist}->{$p};
- $Ext::Fork::POOL->{children} -- if $Ext::Fork::POOL->{childre
+n};
+ $Ext::Fork::POOL->{cidlist}->{$p} = 0; # mark process as d
+one
}
# self reference
@@ -243,6 +244,7 @@
return 1 if $Ext::Fork::POOL->{nonblocking};
while(1){
+ rfork_cleanup();
last if !$Ext::Fork::POOL->{children};
if($Ext::Fork::has_thr){
@@ -262,6 +264,7 @@
=cut
sub rfork_active_children {
+ rfork_cleanup();
return ($Ext::Fork::POOL->{children} ? $Ext::Fork::POOL->{childre
+n} : 0);
}
@@ -391,6 +394,7 @@
sub rfork_kill_children {
my $sig = $_[0];
+ rfork_cleanup();
if(!$sig){
$sig = 'TERM';
}
@@ -410,6 +414,7 @@
sub rfork_list_children {
my ($use_hash) = @_;
+ rfork_cleanup();
if(!$Ext::Fork::POOL->{cidlist}){
return;
@@ -432,6 +437,7 @@
sub rfork_child_dob {
my $pid = $_[0];
+ rfork_cleanup();
if($Ext::Fork::POOL->{cidlist}->{$pid}){
return $Ext::Fork::POOL->{cidlist}->{$pid};
} else {
@@ -439,4 +445,21 @@
}
}
+=head2 rfork_cleanup()
+
+Perform delayed list cleanup.
+
+=cut
+
+sub rfork_cleanup {
+ my @deadpids =
+ grep { $Ext::Fork::POOL->{cidlist}->{$_} == 0 }
+ keys %{ $Ext::Fork::POOL->{cidlist} };
+ foreach (@deadpids)
+ {
+ delete $Ext::Fork::POOL->{cidlist}->{$_};
+ $Ext::Fork::POOL->{children} -- if $Ext::Fork::POOL->{childre
+n};
+ }
+}
+