Ernten Sie Kinder, ohne $ SIG {CHLD} auf IGNORE oder auf einen benutzerdefinierten Signal-Handler zu setzen

7

Ich versuche, einen Socket-Server zu schreiben, der für jede Verbindung forscht. Ich bin erfolgreich gewesen, abgesehen von einem kleinen Vorbehalt: meine Kindprozesse verwenden Net: OpenSSH- & gt; capture2 (), was erfordert, dass $ SIG {CHLD} nicht auf IGNORE oder auf einen benutzerdefinierten Signal-Handler gesetzt wird. Wie kann ich meine Kinder ernten, ohne den Signalhandler zu setzen oder den Elternprozess mit wait oder waitpid zu verlangsamen?

Hier ist mein Servercode:

%Vor%

Wenn ich den Code wie oben gezeigt benutze, funktioniert alles, aber ich lande mit einer Reihe von Zombie-Prozessen. Wenn ich

hinzufüge %Vor%

Die Zombies werden geerntet, aber der Net :: OpenSSH- & gt; capture2 () -Methodenaufruf hat einen verwirrten Rückkehrcode. Ich nehme an, mein Signalhandler stört einige benutzerdefinierte Handler, die Net :: OpenSSH benötigt, um ordnungsgemäß zu funktionieren?

    
Michael 12.08.2010, 03:23
quelle

2 Antworten

11

Gehen Sie voran und richten Sie einen SIGCHLD-Handler im übergeordneten Prozess ein, deaktivieren Sie ihn jedoch in den untergeordneten Prozessen. Fügen Sie beispielsweise unmittelbar nach dem Aufruf von local $SIG{CHLD} ein fork ein.

In den untergeordneten Prozessen stammen die SIGCHLD-Ereignisse aus den Net::OpenSSH -Methoden, und das Modul Net::OpenSSH verarbeitet diese Ereignisse.

Im übergeordneten Prozess stammen SIGCHLD-Ereignisse von Ihren untergeordneten Prozessen. Das sind genau die Ereignisse, an denen Sie interessiert sind und die, die Sie behandeln müssen, um Zombies zu verhindern.

    
mob 12.08.2010, 04:15
quelle
8

Wenn Sie Kinder niemals ignorieren und Net :: OpenSSH im selben Prozess verwenden müssen, können Sie möglicherweise $SIG{CHLD} = 'IGNORE' in den Prozessen verwenden, die Net :: OpenSSH nicht verwenden (z. B. den Einzelserverprozess, der sich ausschaltet "Auto-reapped" children) und auf $SIG{CHLD} = 'DEFAULT' in den Prozessen zurücksetzen, die Net :: OpenSSH verwenden (zB die untergeordneten Elemente des Servers).

Alternativ können Sie nach jeder neuen Clientverbindung eine nicht blockierende waitpid Schleife verwenden . Sie können immer noch mit einem oder mehreren Zombies herumhängen, aber sie werden alle bei der nächsten Verbindung geerntet. Wenn Sie zu select wechseln (oder etwas wie IO :: Select ), können Sie eine Obergrenze für die" Lebensdauer "der Zombies festlegen, indem Sie eine Auswahl an Ihrem Horch-Socket vornehmen und eine Runde Nicht-Blockieren durchführen Zombie ernten nach jeder Zeitüberschreitung sowie jeder "socket ready" Rückkehr.

Aus dem Abschnitt waitpid von perlfunc-Manpage :

  

Wenn Sie sagen

%Vor%      

Dann können Sie eine blockierungsfreie Wartezeit für alle ausstehenden Zombieprozesse einhalten. Non-blocking wait ist auf Computern verfügbar, die entweder die Systemaufrufe waitpid (2) oder wait4 (2) unterstützen.

    
Chris Johnsen 12.08.2010 04:13
quelle