In perl, zu töten Kind und seine Kinder, als Kind wurde erstellt mit open
Hier ist mein code, mit Fehlerbehandlung und andere Sachen entfernt, die für Klarheit:
sub launch_and_monitor {
my ($script, $timeout) = @_;
sub REAPER {
while ((my $child = waitpid(-1, &WNOHANG)) > 0) {}
$SIG{CHLD} = \&REAPER;
}
$SIG{CHLD} = \&REAPER;
my $pid = fork;
if (defined $pid) {
if ($pid == 0) {
# in child
monitor($timeout);
}
else {
launch($script);
}
}
}
Den Start sub führt ein shell-Skript, das wiederum startet andere Prozesse, etwa so:
sub launch($) {
my ($script) = @_;
my $pid = open(PIPE, "$script|");
# write pid to pidfile
if ($pid != 0) {
while(<PIPE>) {
# do stuff with output
}
close(PIPE) or die $!;
}
}
Den monitor sub im Grunde nur darauf wartet für eine bestimmte Zeit und dann versucht zu töten das shell-Skript.
sub monitor($) {
my ($timeout) = @_;
sleep $timeout;
# check if script is still running and if so get pid from pidfile
if (...) {
my $pid = getpid(...);
kill 9, $pid;
}
}
Dieser tötet das Skript, aber es tötet nicht, es ist sub-Prozesse. Wie zu beheben?
- Ich habe keine Antwort auf deine Hauptfrage, aber ich würde empfehlen, machen
REAPER
eine anonyme sub, z.B.my $reaper = sub { ... }; $SIG{CHLD} = $reaper;
Setzen eines namens sub in einem anderen sub nicht verstecken Sie von anderen Bereichen. Alle genannten subs sind package-Symbole in Perl - speculation.org/garrick/kill-9.html
- guter Punkt, danke für den Hinweis
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie dies tun mit Gruppen, wenn Ihr Betriebssystem unterstützt wird. Sie benötigen, um den Skript-Prozess zu einem Prozess Gruppenleiter. Die Kind-Prozesse, die es ausgeführt wird, übernehmen die Prozess-Gruppe von Ihrer Muttergesellschaft. Sie können dann mittels kill sendet ein signal an jeden Prozess in der Gruppe zur gleichen Zeit.
In
launch()
, müssen Sie ersetzen dieopen
Linie mit einer Gabel. Dann in das Kind, Sie nennen würdesetpgrp()
vor exec ' Ing der Befehl. Etwas, das wie folgt funktionieren sollte:Später, zu töten, die Skript-Prozess und dessen Kinder, Annulliere die Prozess-ID, die du bist-Signal:
kill '-9', $pid
.Im Allgemeinen, ich glaube nicht, dass Sie erwarten können Signale weitergegeben werden in alle untergeordneten Prozesse; dies ist nicht spezifisch für perl.
Sagte, Sie könnten in der Lage sein, das Verfahren Gruppe signal-Funktion integriert perl kill():
Müssen Sie wahrscheinlich verwenden setpgrp() auf Ihre (direkte) Kind-Prozess, dann ändern Sie Ihre kill-Aufruf etwas wie:
Versuchen Sie, hinzufügen:
oben Ihre
launch_and_monitor
Funktion. Dies wird Ihre Prozesse in einer separaten Sitzung, und führen die Dinge zu beenden, wenn die "session leader" (also der master) beendet.Tötung eines processgroup arbeiten, aber vergessen Sie nicht, die Eltern können getötet werden, auch allein. Vorausgesetzt, untergeordnete Prozesse, die eine Ereignis-Schleife, können Sie den übergeordneten socket erstellt wurde, in ein socketpair vor tut die Gabel() für validness. In der Tat, wählen Sie() sauber beendet, wenn das parent-Buchse ist Weg, alles, das getan werden muss, ist überprüfen Sie die Steckdose.
E. g.:
Läuft so: