Forkserver tends to die with segmentation faults in the signal handler as several people on the list noticed. It also sometimes misses the death of a child. This patch moves the REAPER into the main loop. It now checks for dead children after each accept and once every second if there are more then $MAXCONN children. This means that zombies hang around until the next client connects. A bit untidy, but shouldn't be a real problem. forkserver has been rock-solid for me since this patch.
-- _ | Peter J. Holzer | Ich sehe nun ein, dass Computer wenig |_|_) | Sysadmin WSR | geeignet sind, um sich was zu merken. | | | [EMAIL PROTECTED] | __/ | http://www.hjp.at/ | -- Holger Lembke in dan-am
--- qpsmtpd-forkserver.no_sigcld Tue May 31 21:13:05 2005
+++ qpsmtpd-forkserver Wed Jun 1 09:07:02 2005
@@ -58,7 +58,6 @@
my %childstatus = ();
sub REAPER {
- $SIG{CHLD} = \&REAPER;
while ( defined(my $chld = waitpid(-1, WNOHANG)) ){
last unless $chld > 0;
warn("$$ cleaning up after $chld\n");
@@ -72,7 +71,6 @@
exit(0);
}
-$SIG{CHLD} = \&REAPER;
$SIG{INT} = \&HUNTSMAN;
$SIG{TERM} = \&HUNTSMAN;
@@ -129,10 +127,12 @@
while (1) {
+ REAPER();
my $running = scalar keys %childstatus;
while ($running >= $MAXCONN) {
::log(LOGINFO,"Too many connections: $running >= $MAXCONN. Waiting one
second.");
sleep(1) ;
+ REAPER();
$running = scalar keys %childstatus;
}
my $hisaddr = accept(my $client, $server);
@@ -151,6 +151,8 @@
# If we for-loop directly over values %childstatus, a SIGCHLD
# can call REAPER and slip $rip out from under us. Causes
# "Use of freed value in iteration" under perl 5.8.4.
+ #
+ # REAPER isn't a signal handler anymore, so this can't happen.
my @rip = values %childstatus;
foreach my $rip (@rip) {
++$num_conn if (defined $rip && $rip eq $iaddr);
pgp2tDQfNatTt.pgp
Description: PGP signature
