Author: radu
Date: Thu Sep 4 04:41:13 2008
New Revision: 939
Modified:
trunk/Changes
trunk/qpsmtpd-prefork
Log:
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.
Modified: trunk/Changes
==============================================================================
--- trunk/Changes (original)
+++ trunk/Changes Thu Sep 4 04:41:13 2008
@@ -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
and loading the plugins, to give the init scripts a chance to detect
failed startups due to broken configuration or plugins (Diego d'Ambra)
Modified: trunk/qpsmtpd-prefork
==============================================================================
--- trunk/qpsmtpd-prefork (original)
+++ trunk/qpsmtpd-prefork Thu Sep 4 04:41:13 2008
@@ -47,6 +47,8 @@
my %children;
my $chld_pool;
my $chld_busy;
+my @children_term; # terminated children, their death pending processing
+ # by the main loop
my $d; # socket
# default settings
@@ -284,35 +286,41 @@
# cleanup after child dies
sub reaper {
my $stiff;
- my @stiffs;
while (($stiff = waitpid(-1, &WNOHANG)) > 0) {
my $res = WEXITSTATUS($?);
info("child terminated, pid: $stiff (status $?, res: $res)");
delete $children{$stiff}; # delete pid from children
# 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, [EMAIL PROTECTED], undef, undef);
$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
#ret0: void
sub main_loop {
while (1) {
- # sleep EXPR seconds or until signal (i.e. child death) is received
- my $sleept = sleep $loop_sleep;
+ # if there is no child death to process, then sleep EXPR seconds
+ # 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);
- # get number of busy children, if sleep wasn't interrupted by signal
- $chld_busy = shmem_opt(undef, undef, undef, undef, 1)
- if ($sleept == $loop_sleep);
+ # get number of busy children
+ if (@children_term) {
+ # remove dead children info from shared memory
+ $chld_busy = shmem_opt(undef, [EMAIL PROTECTED], 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)
if (defined($chld_busy)) {