Wie man Kindprozess sterben lässt, nachdem Elternteile verlassen?
Angenommen ich habe ein Prozess, der erzeugt genau ein Kind-Prozess. Nun, wenn der übergeordnete Prozess beendet, für welchen Gründen auch immer (normal oder abnorm, von töten, ^C, assert-Fehler oder sonst etwas) ich möchte, dass der Kind-Prozess zu sterben. Wie man das richtig?
Einige ähnliche Frage auf stackoverflow:
- (zuvor gestellte) Wie kann ich dazu beitragen, dass ein Kind-Prozess zu beenden, wenn die Eltern nicht?
- (bat später) Sind Kind-Prozesse erzeugt mit fork() automatisch getötet, wenn die Eltern getötet werden?
Einige ähnliche Frage auf stackoverflow für Windows:
- Wie kann ich automatisch zerstören Kind Prozesse in Windows?
- Töten Kind-Prozess als Eltern-Prozess gekillt
InformationsquelleAutor der Frage Paweł Hajdan | 2008-11-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Kind kann Fragen kernel zu liefern
SIGHUP
(oder anderes signal), wenn ein Elternteil stirbt durch Angabe der optionPR_SET_PDEATHSIG
imprctl()
syscall wie diese:prctl(PR_SET_PDEATHSIG, SIGHUP);
Sehen
man 2 prctl
für details.Edit: ist Das Linux-nur
InformationsquelleAutor der Antwort qrdl
Ich versuche, dieses problem zu lösen, und da mein Programm muss laufen auf OS X, Linux-only-Lösung funktionierte nicht für mich.
Kam ich zu dem gleichen Schluss wie die anderen Leute auf dieser Seite -- es gibt nicht einen POSIX-kompatiblen Art und Weise der Benachrichtigung ein Kind, wenn ein Elternteil stirbt. Also ich kludged bis die nächste beste Sache-das Kind poll.
Wenn ein Elternprozess stirbt (aus irgendeinem Grund) die Eltern-Prozess wird Prozess 1. Wenn das Kind einfach Umfragen in regelmäßigen Abständen überprüfen zu können, wenn das übergeordnete Element ist 1. Wenn es ist, sollte das Kind verlassen.
Dies ist nicht ideal, aber es funktioniert, und es ist einfacher, als die TCP-socket - /lockfile-polling Lösungen vorgeschlagen, an anderer Stelle auf dieser Seite.
InformationsquelleAutor der Antwort Schof
Ich dies erreicht haben, die in der Vergangenheit von der "original" - code in der "Kind" und das "hervorgebracht" - code in der "Eltern" (das heißt: kehren Sie die üblichen Sinne der Prüfung nach
fork()
). Dann Falle SIGCHLD in der "gespawnt" code...Nicht möglich sein kann, in deinem Fall aber nett, wenn es funktioniert.
InformationsquelleAutor der Antwort dmckee
Wenn Sie nicht zu ändern, wird der Kind-Prozess, können Sie versuchen, so etwas wie die folgenden:
Dies führt das Kind in einem shell-Prozess mit job-Steuerung aktiviert. Der Kind-Prozess erzeugt wird, in den hintergrund. Die shell wartet, bis ein newline (oder EOF), dann tötet das Kind.
Wenn der Elternteil stirbt-egal, was der Grund dafür-es wird in der Nähe seiner Ende der Leitung. Das Kind shell erhalten ein EOF vom Lesen und gehen Sie töten die im hintergrund Kind-Prozess.
InformationsquelleAutor der Antwort Phil Rutschman
Vollständigkeit halber. Unter macOS können Sie kqueue:
InformationsquelleAutor der Antwort neoneye
Tut, wird der Kind-Prozess eine pipe nach/vom übergeordneten Prozess? Wenn ja, würden Sie erhalten ein SIGPIPE, wenn schreiben, oder bekommen EOF beim Lesen - diese Bedingungen nachgewiesen werden konnte.
InformationsquelleAutor der Antwort MarkR
Inspiriert von einer anderen Antwort hier, ich kam mit der folgenden all-POSIX-Lösung. Die Allgemeine Idee ist die Erstellung einer intermediate-Prozess zwischen dem Elternteil und dem Kind, dass hat einen Zweck: Benachrichtigung, wenn der Elternteil stirbt, und explizit töten das Kind.
Diese Art von Lösung ist nützlich, wenn Sie den code in das Kind kann nicht geändert werden.
Gibt es zwei kleine Einschränkungen, die mit dieser Methode:
Nebenbei, der eigentliche code, den ich verwende, ist in Python. Hier ist es der Vollständigkeit halber:
InformationsquelleAutor der Antwort Greg Hewgill
Unter Linux installieren möchten, können Sie ein Eltern-Tod-Signals in das Kind, z.B.:
Beachten Sie, dass die Speicherung der parent-Prozess-id, bevor Sie die Gabel und testen Sie in dem Kind nach
prctl()
beseitigt eine race-condition zwischenprctl()
und den Ausgang des Prozesses, genannt das Kind.Beachten Sie auch, dass die Eltern den Tod-signal für das Kind geklärt ist in neu erstellten Kinder von seiner eigenen. Es ist nicht betroffen von einem
execve()
.Die Prüfung kann vereinfacht werden, wenn wir sicher sind, dass der system-Prozess-wer ist verantwortlich für die Annahme aller Waisen hat die PID 1:
Vertrauen darauf, dass ein system-Prozess sein
init
und mit der PID 1 ist nicht tragbar, obwohl. POSIX.1-2008 gibt:Traditionell, system-Prozess-Annahme aller Kinder ist die PID 1 hat, d.h. init - welches ist der Urahn aller Prozesse.
Auf moderne Systeme wie Linux oder FreeBSD einem anderen Prozess haben könnte, die Rolle. Zum Beispiel auf Linux, einen Prozess aufrufen kann
prctl(PR_SET_CHILD_SUBREAPER, 1)
etabliert sich als system-Prozess, der erbt alle Waisen seiner Nachkommen (vgl. ein Beispiel Fedora-25).InformationsquelleAutor der Antwort maxschlepzig
Ich glaube nicht, dass es möglich ist, zu garantieren, dass nur mit standard-POSIX-Aufrufe. Wie im echten Leben, wenn ein Kind hervorgebracht, es hat ein eigenes Leben.
Es ist möglich, dass der Elternprozess fangen die meisten möglichen Kündigung Ereignisse, und versuchen zu töten, wird der Kind-Prozess an diesem Punkt, aber es gibt immer einige, die können nicht abgefangen werden.
Zum Beispiel, kann kein Prozess fangen
SIGKILL
. Wenn der kernel verarbeitet dieses signal wird es töten, den angegebenen Prozess keine Benachrichtigung zu diesem Prozess auch immer.Erweitern, die Analogie, die nur standard Weg, es zu tun ist für das Kind, Selbstmord zu Begehen, wenn es feststellt, dass es nicht mehr über ein Elternteil.
Gibt es eine Linux-nur Weg, es zu tun mit
prctl(2)
- siehe andere Antworten.InformationsquelleAutor der Antwort Alnitak
Installieren trap-handler zu fangen, SIGINT, das tötet aus Ihrer Kind-Prozess, wenn es noch lebt, obwohl andere Poster korrekt sind, dass es sich nicht durchsetzen SIGKILL.
Öffnen .lockfile mit exklusivem Zugang und das Kind zu Umfrage, versuchen, Sie zu öffnen - wenn das öffnen erfolgreich, wird der Kind-Prozess sollte die Ausfahrt
InformationsquelleAutor der Antwort Paul Betts
Als andere Leute haben darauf hingewiesen, sich auf die parent-pid 1 werden, wenn der Elternteil verlässt, ist nicht tragbar. Anstatt zu warten, für einen bestimmten parent-Prozess-ID, warten, nur für die ID zu ändern:
Fügen Sie einen Mikro-Schlaf als erwünscht, wenn Sie nicht wollen, um Abfragen auf Hochtouren.
Diese option scheint einfacher für mich als mit einem Rohr oder sich auf Signale.
InformationsquelleAutor der Antwort user2168915
Ich denke, eine schnelle und schmutzige Art und Weise ist das erstellen einer pipe zwischen Kind und Eltern. Wenn der parent beendet wird, Kinder erhalten ein SIGPIPE.
InformationsquelleAutor der Antwort Yefei
Diese Lösung bei mir funktioniert:
Dieser war für einen Arbeiter-Art Prozess, dessen Existenz erst sinnvoll, wenn die Eltern noch am Leben war.
InformationsquelleAutor der Antwort joonas.fi
Einige Poster haben es bereits erwähnt-Rohre und -
kqueue
. In der Tat kann man auch ein paar der angeschlossenen Unix-domain-sockets durch diesocketpair()
nennen. Der socket-Typ sollteSOCK_STREAM
.Lassen Sie uns nehmen Sie an, Sie haben die zwei-socket-Datei-Deskriptoren fd1, fd2. Jetzt
fork()
erstellen der Kind-Prozess, die Erben der fds. In der übergeordneten, die Sie in der Nähe fd2 und in dem Kind, das Sie in der Nähe fd1. Nun, jeder Prozess kannpoll()
den noch offenen fd auf seinem eigenen Ende für diePOLLIN
Veranstaltung. Solange jede Seite muss nicht explizitclose()
seine fd während der normalen Lebensdauer, können Sie ziemlich sicher sein, dass einPOLLHUP
Flagge zeigen sollte, dem anderen die Kündigung (egal, sauber oder nicht). Auf informiert diesem Fall ist, kann das Kind entscheiden, was zu tun ist (z.B. zu sterben).Können Sie versuchen, kompilieren Sie die oben genannten proof-of-concept-code, und führen Sie es in ein terminal wie
./a.out &
. Sie haben etwa 100 Sekunden zum Experimentieren mit der Tötung der Eltern-PID durch verschiedene Signale, oder es wird einfach zu beenden. In beiden Fällen sollten Sie sehen die Meldung "Kind: Eltern-hung up".Verglichen mit der Methode, mit
SIGPIPE
handler diese Methode erfordert nicht versuchen, diewrite()
nennen.Diese Methode ist auch symmetrischend.h. die Prozesse können mit dem gleichen Kanal zu überwachen, den jeweils anderen Existenz.
Diese Lösung fordert nur die POSIX-Funktionen. Ich habe versucht, diese in Linux und FreeBSD. Ich denke, es sollte funktionieren, auf anderen Unices, aber ich habe nicht wirklich getestet.
Siehe auch:
unix(7)
Linux-man-Seiten,unix(4)
für FreeBSDpoll(2)
socketpair(2)
socket(7)
auf Linux.InformationsquelleAutor der Antwort Cong Ma
Unter POSIXdie
exit()
_exit()
und_Exit()
Funktionen sind definiert:Also, wenn Sie arrangieren für den übergeordneten Prozess controlling-Prozess für die Prozess-Gruppe, sollte das Kind bekommen, ein SIGHUP-signal, wenn der parent beendet wird. Ich bin mir nicht absolut sicher, dass passiert, wenn die Eltern abstürzt, aber ich denke, es ist. Sicherlich, für die nicht-crash-Fällen, es sollte funktionieren.
Beachten Sie, dass Sie gelesen haben, eine ganze Menge von Kleingedruckte, einschließlich der grundlegenden Definitionen (Begriffsbestimmungen) Abschnitt, sowie die System-Dienste-Informationen für
exit()
undsetsid()
undsetpgrp()
- komplettes Bild. (So würde ich das auch!)InformationsquelleAutor der Antwort Jonathan Leffler
Wenn Sie senden ein signal an die pid 0, z.B. mit
dass signal gesendet wird, um den gesamten Prozess der Gruppe, so effektiv zu töten das Kind.
Können Sie es testen, einfach mit etwas wie:
Wenn du dann die Taste ^D, du wirst sehen, der text
"Terminated"
als Indiz dafür, dass der Python-interpreter in der Tat getötet, anstatt nur verlassen, weil stdin geschlossen wurde.InformationsquelleAutor der Antwort Thorbiörn Fritzon
Falls es relevant ist, wer sonst, wenn ich spawn JVM-Instanzen in Gabel-Kind-Prozesse aus C++, der einzige Weg, ich könnte das JVM-Instanzen zu beenden, richtig, nachdem der parent-Prozess abgeschlossen wurde, das folgende zu tun. Ich hoffe, jemand kann geben Sie feedback in den Kommentaren, wenn dies nicht der beste Weg, dies zu tun.
1) Rufen Sie
prctl(PR_SET_PDEATHSIG, SIGHUP)
auf die Gabel-Kind-Prozess, wie bereits vorgeschlagen, vor dem starten der Java-Anwendung überexecv
und2) Fügen Sie einen shutdown-hook um die Java-Anwendung, Umfragen, bis seine Eltern PID = 1, dann machen Sie eine harte
Runtime.getRuntime().halt(0)
. Das polling erfolgt durch die Einführung einer separaten shell, läuft dasps
Befehl (Siehe: Wie finde ich die PID in Java oder JRuby auf Linux?).BEARBEITEN 130118:
Scheint es, dass war keine robuste Lösung. Ich bin immer noch kämpfen, ein bisschen zu verstehen, die Nuancen, was Los ist, aber ich war trotzdem manchmal verwaiste JVM-Prozesse beim ausführen dieser Anwendungen in der Bildschirm/SSH-Sitzungen.
Anstelle von polling für die PPID in die Java-app, ich hatte einfach den shutdown-hook Bereinigung durchführen, gefolgt von einem schwer halt, wie oben. Dann machte ich sicher, dass invoke
waitpid
im C++ Eltern app auf die erzeugte child-Prozess, wenn es Zeit war, zu kündigen, alles. Dies scheint eine robustere Lösung, wie der Kind-Prozess wird sichergestellt, dass es sich beendet, während die Eltern auf vorhandene Referenzen, um sicherzustellen, dass seine Kinder zu beenden. Vergleichen Sie dies mit der vorherigen Lösung hatte der übergeordnete Prozess beendet, wenn Sie zufrieden waren und die Kinder versuchen Sie herauszufinden, wenn Sie waren verwaist, vor dem beenden.InformationsquelleAutor der Antwort jasterm007
Obwohl 7 Jahre vergangen, ich habe einfach dieses Problem, wie ich bin mit SpringBoot Anwendung starten muss, um webpack-dev-server während der Entwicklung und benötigt um es zu töten, wenn der backend-Prozess beendet.
Ich versuche es mal mit
Runtime.getRuntime().addShutdownHook
aber es hat funktioniert auf Windows 10 aber nicht auf Windows 7.Habe ich es zu ändern verwenden Sie einen dedizierten thread, der wartet, bis der Prozess zu beenden oder für
InterruptedException
scheint, um korrekt zu funktionieren auf beiden Windows-Versionen.InformationsquelleAutor der Antwort Ido Ran
Wenn ein Elternteil stirbt, PPID von Waisen änderung auf 1 - Sie müssen nur überprüfen Sie Ihre eigenen PPID.
In gewisser Weise ist dies polling, oben erwähnt.
hier ist shell Stück:
InformationsquelleAutor der Antwort alex K
Fand ich 2 Lösungen, die beide nicht perfekt.
1.Töten Sie alle Kinder von kill (pid -), wenn empfangen SIGTERM-signal.
Natürlich kann diese Lösung nicht mit "kill -9", aber es tun sich für die meisten Gehäuse und sehr einfach, denn es müssen nicht an alle Kind-Prozesse.
Durch den gleichen Weg, können Sie 'exit' - handler wie oben beschriebenen Weise, wenn Sie anrufen Prozess.Ausfahrt irgendwo.
Hinweis: Strg+C und plötzliche Absturz wurden automatisch verarbeitet, die von OS zu töten-Prozess-Gruppe, also nicht mehr hier.
2.Verwenden chjj/pty.jsum zu laichen, die Ihren Prozess mit controlling-terminal angehängt.
Wenn Sie zu töten Laufenden Prozess sowieso noch kill -9, alle Kind-Prozesse werden automatisch getötet zu werden (durch OS?). Ich denke, dass da die geltenden Verfahren halten andere Seite des Terminals, so dass, wenn der aktuelle Prozess stirbt, wird der Kind-Prozess bekommen SIGPIPE so stirbt.
InformationsquelleAutor der Antwort osexp2003
Ist mir gelungen, ein tragbares, nicht-polling-Lösung mit 3-Prozesse durch Missbrauch terminal control und Sitzungen. Das ist geistige Onanie, aber funktioniert.
Der trick ist:
So:
Mängel:
InformationsquelleAutor der Antwort Marek Dopiera
Historisch aus der UNIX v7, der Prozess system hat erkannt, dass orphanity der Prozesse durch die überprüfung ein Prozess,' parent-id. Wie sage ich, dass, historisch gesehen, die
init(8)
system-Prozess ist ein spezieller Prozess, durch nur einen einzigen Grund: Es kann nicht sterben. Es kann nicht sterben, weil der kernel Algorithmus zum Umgang mit dem zuweisen einer neuen parent-Prozess-id, hängt von dieser Tatsache. wenn ein Prozess ein, führt dieexit(2)
Aufruf (durch einen Prozess, system call oder durch externe task sendet es ein signal oder dergleichen), der kernel ordnet alle Kinder in diesem Prozess die id des init-Prozess als Eltern-Prozess-id. Dies führt zu der die meisten einfachen test, und die meisten tragbaren Weg zu wissen, wenn ein Prozess hat Waisenkind. Nur überprüfen Sie das Ergebnis dergetppid(2)
- system nennen, und wenn es ist die Prozess-id desinit(2)
Prozess, dann wird der Prozess bekam Waise vor dem system-Aufruf.Zwei Fragen ergeben sich aus diesem Ansatz, dass kann zu Problemen führen:
init
Prozess zu jeder Benutzer-Prozess, Wie können wir also sicherstellen, dass der init-Prozess wird immer Eltern aller orphan-Prozesse? Gut, in derexit
system-call-code, es gibt eine explizite überprüfen, um zu sehen, ob der Prozess der Ausführung der Aufruf der init-Prozess (der Prozess mit der pid, die gleich 1 ist) und wenn das der Fall ist, die kernel-Panik (Es sollte nicht in der Lage sein, mehr zur Aufrechterhaltung der Prozess-Hierarchie), so ist es nicht gestattet, für den init-Prozess zu tun, einexit(2)
nennen.1
aber das ist garantiert nicht die POSIX-Ansatz, dass die Staaten (wie ausgesetzt in der anderen Antwort), dass nur ein system die Prozess-id reserviert für diesen Zweck. Fast keine posix-Implementierung der dies tut, und Sie können davon ausgehen, in der original-unix abgeleiteten Systemen, die mit1
als Antwortgetppid(2)
system call ist genug, um davon ausgehen, der Prozess ist Waise. Ein weiterer Weg, um zu überprüfen ist es, einegetppid(2)
nur nach der Gabel und vergleichen Sie diesen Wert mit dem Ergebnis, einen neuen Anruf. Dies ist einfach nicht in allen Fällen funktionieren, da beide nennen sind nicht atomar zusammen, und der übergeordnete Prozess sterben nach derfork(2)
und vor dem erstengetppid(2)
system nennen. Der Prozessparent id only changes once, when its parent does an
exit(2)call, so this should be enough to check if the
getppid(2)result changed between calls to see that parent process has exit. This test is not valid for the actual children of the init process, because they are always children of
init(8)`, aber Sie können sicher davon ausgehen, diese Prozesse als kein Elternteil entweder (außer, wenn Sie Ersatz in einem system der init-Prozess)InformationsquelleAutor der Antwort Luis Colorado
Einen anderen Weg, dies zu tun, ist Linux-spezifisch ist, haben die Eltern in einer neuen PID-namespace. Es wird dann PID 1 in diesem namespace, und wenn er beendet es, alle es die Kinder sofort getötet mit
SIGKILL
.Leider, um erstellen Sie eine neue PID-namespace müssen Sie
CAP_SYS_ADMIN
. Aber, diese Methode ist sehr wirkungsvoll und erfordert keine wirkliche änderung an den Elternteil oder die Kinder über den Start der Eltern.Sehen clone(2)pid_namespaces(7)und Freigabe aufheben(2).
InformationsquelleAutor der Antwort Omnifarious