Christian: Multithreaded Server - $SIG{CHLD} = sub { wait } beendet Server

Beitrag lesen

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