So, ausprobiert, etwas korrigiert und es funzt endlich! ;-)
Am Ende sieht der Code dann etwa so aus:
my $waitedpid = 0;
my $terminated_pid = 0;
sub childhandler {
my $child;
# Auf ALLE kinder warten
while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
$terminated_pid = $waitedpid; # <-- neu
}
# Portabilität mit Systemen, auf denen der Signalhandler neu gesetzt
# werden muss, nachdem er ausgeführt wurde
$SIG{'CHILD'} = \&childhandler;
}
$SIG{'CHILD'} = \&childhandler;
und dann in der Schleife:
for ($terminated_pid = 0;
($client = $sock->accept()) || $terminated_pid;
$terminated_pid = 0) {
next if ($terminated_pid);
# Hier jetzt der normale Code vom inneren der Schleife _mit_
# $client->close, damit dies nur bei Clients ausgeführt wird
# und nicht, wenn die Schleifenbedingung durch ein totes
# Kind zustande kommt.
$client->close;
}
Bei deinem Code wird die while-Bedigung im SIGCHLD-Handler nochmals abgefragt und dann liefert waitpid 0 (gibt noch Kinder) oder -1 (keine Kinder mehr) und nicht mehr die PID des Kindes. Mit der zusätzlichen Variable $terminated_pid ist die PID nun wirklich im Hauptprogramm nutzbar.
Alternativ fällt mir gerade ein, dass man im Handler auch ein return; in die while-Schleife setzen könnte, um eine erneute Auswertung von waitpid zu verhindern.
Viele Grüße
Christian