Inside the main loop skip the sleep when children have exited. Instead, proceed directly to the pool adjustment. While at it, simplify processing by moving the update of shared memory from the SIGCHLD handler to the main loop.

git-svn-id: https://svn.perl.org/qpsmtpd/trunk@939 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
Radu Greab 2008-09-04 11:41:13 +00:00 committed by Ask Bjørn Hansen
parent 18d1b9f1da
commit e4f0cb0f8c
2 changed files with 23 additions and 12 deletions

View File

@ -1,3 +1,6 @@
prefork: the children pool size was sometimes not adjusted immediately
after the exit of children (reported by Diego d'Ambra)
async, prefork: detach and daemonize only after reading the configuration async, prefork: detach and daemonize only after reading the configuration
and loading the plugins, to give the init scripts a chance to detect and loading the plugins, to give the init scripts a chance to detect
failed startups due to broken configuration or plugins (Diego d'Ambra) failed startups due to broken configuration or plugins (Diego d'Ambra)

View File

@ -47,6 +47,8 @@ my $chld_shmem; # shared mem to keep track of children (and their connections)
my %children; my %children;
my $chld_pool; my $chld_pool;
my $chld_busy; my $chld_busy;
my @children_term; # terminated children, their death pending processing
# by the main loop
my $d; # socket my $d; # socket
# default settings # default settings
@ -284,35 +286,41 @@ sub spawn_children {
# cleanup after child dies # cleanup after child dies
sub reaper { sub reaper {
my $stiff; my $stiff;
my @stiffs;
while (($stiff = waitpid(-1, &WNOHANG)) > 0) { while (($stiff = waitpid(-1, &WNOHANG)) > 0) {
my $res = WEXITSTATUS($?); my $res = WEXITSTATUS($?);
info("child terminated, pid: $stiff (status $?, res: $res)"); info("child terminated, pid: $stiff (status $?, res: $res)");
delete $children{$stiff}; # delete pid from children delete $children{$stiff}; # delete pid from children
# add pid to array so it later can be removed from shared memory # add pid to array so it later can be removed from shared memory
push @stiffs, $stiff; push @children_term, $stiff;
} }
# remove connection info from shared memory and get number
# of busy children (use by main_loop)
$chld_busy = shmem_opt(undef, \@stiffs, undef, undef);
$SIG{CHLD} = \&reaper; $SIG{CHLD} = \&reaper;
} }
#main_loop: main loop (spawn new children) #main_loop: main loop. Either processes children that have exited or
# periodically scans the shared memory for children that are not longer
# alive. Spawns new children when necessary.
#arg0: void #arg0: void
#ret0: void #ret0: void
sub main_loop { sub main_loop {
while (1) { while (1) {
# sleep EXPR seconds or until signal (i.e. child death) is received # if there is no child death to process, then sleep EXPR seconds
my $sleept = sleep $loop_sleep; # or until signal (i.e. child death) is received
sleep $loop_sleep unless @children_term;
# block CHLD signals to avoid race, anyway does it matter? # block CHLD signals to avoid race
my $sigset = block_signal(SIGCHLD); my $sigset = block_signal(SIGCHLD);
# get number of busy children, if sleep wasn't interrupted by signal # get number of busy children
$chld_busy = shmem_opt(undef, undef, undef, undef, 1) if (@children_term) {
if ($sleept == $loop_sleep); # remove dead children info from shared memory
$chld_busy = shmem_opt(undef, \@children_term, undef, undef);
@children_term = ();
}
else {
# just check the shared memory
$chld_busy = shmem_opt(undef, undef, undef, undef, 1);
}
# calculate children in pool (if valid busy children number) # calculate children in pool (if valid busy children number)
if (defined($chld_busy)) { if (defined($chld_busy)) {