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?
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.
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.
Tags und Links perl parent-child signal-handling