it-swarm.com.de

Wie kann ich bewirken, dass ein untergeordneter Prozess beendet wird, wenn der übergeordnete Prozess dies tut

Ich starte einen untergeordneten Prozess mit ProcessBuilder und muss den untergeordneten Prozess beenden, wenn der übergeordnete Prozess dies tut. Unter normalen Umständen stoppt mein Code das Kind ordnungsgemäß. Wenn ich jedoch das Betriebssystem dazu bringe, das übergeordnete Element zu beenden, läuft das Kind weiter.

Gibt es eine Möglichkeit, den untergeordneten Prozess mit dem übergeordneten Element zu "binden", sodass es beendet wird, wenn das übergeordnete Element getötet wird?


Ähnliche Fragen:

40
Alex

Es gibt keine Verbindung zwischen einem untergeordneten Prozess und seinem übergeordneten Prozess. Sie kennen zwar die Prozess-ID des anderen, aber es gibt keine feste Verbindung zwischen ihnen. Was Sie über einen Orphan-Prozess sprechen . Und es ist ein Anliegen auf Betriebssystemebene. Das bedeutet, dass jede Lösung wahrscheinlich plattformabhängig ist. 

Das Einzige, woran ich denken kann, ist, das Kind regelmäßig den Status seiner Eltern überprüfen zu lassen und zu beenden, ob das Elternteil heruntergefahren ist. Ich glaube nicht, dass das alles so zuverlässig wäre.

18
sblundy

Sie können zwar nicht vor einem harten Abbruch schützen (z. B. SIGKILL unter Unix), Sie können jedoch auch vor anderen Signalen schützen, die dazu führen, dass Ihr übergeordneter Prozess herunterfährt (z. B. SIGINT) und Ihren untergeordneten Prozess bereinigt. Sie können dies mit Hilfe von Shutdown-Hooks erreichen: siehe Runtime # addShutdownHook sowie eine verwandte SO - Frage hier .

Ihr Code könnte ungefähr so ​​aussehen:

String[] command;
final Process childProcess = new ProcessBuilder(command).start();

Thread closeChildThread = new Thread() {
    public void run() {
        childProcess.destroy();
    }
};

Runtime.getRuntime().addShutdownHook(closeChildThread); 
33
Greg Case

Sie können einfach einen Thread von System.in aus im untergeordneten Prozess lesen. Wenn Sie nicht an stdin Ihres Kindes schreiben, wird es niemand anderes tun, und der Thread blockiert "für immer". Sie erhalten jedoch ein EOF (oder eine Ausnahme), wenn der übergeordnete Prozess beendet wird oder auf andere Weise stirbt. So können Sie auch das Kind herunterfahren. (Kindprozess wurde mit Java.lang.ProcessBuilder gestartet)

15
tomkri

Stellen Sie einen Hacker-Weg bereit, der mit der Antwort von @tomkri ähnlich ist, und geben Sie auch den Demo-Code an.

Wenn Ihr untergeordneter Prozess keinen Eingabestrom benötigt, leiten Sie den untergeordneten Prozess-Eingabestrom einfach zum Eingabestrom des übergeordneten Prozesses um. Fügen Sie dann in Child einen Thread hinzu, um den Eingabestrom immer zu lesen. Wenn dieser Thread nichts aus dem Eingabestrom lesen kann, wird dieser untergeordnete Prozess beendet. Der übergeordnete Prozess wird also beendet -> Der Eingabestrom des übergeordneten Elements ist nicht vorhanden. -> Der Eingabestrom des untergeordneten Elements ist nicht vorhanden.

Hier ist der Demo-Code alles in Java.

Übergeordneter Prozess:

package process.parent_child;

import Java.io.File;
import Java.io.IOException;
import Java.lang.ProcessBuilder.Redirect;

public class ParentProc {

    public static void main(String[] args) {
        System.out.println("I'm parent.");

        String javaHome = System.getProperty("Java.home");
        String javaBin = javaHome + File.separator + "bin" + File.separator + "Java";
        ProcessBuilder builder = new ProcessBuilder(javaBin, "process.parent_child.ChildProc");

        // Redirect subprocess's input stream to this parent process's input stream.
        builder.redirectInput(Redirect.INHERIT);
        // This is just for see the output of child process much more easily.
        builder.redirectOutput(Redirect.INHERIT);
        try {
            Process process = builder.start();
            Thread.sleep(5000);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Parent exits.");
    }
}

Kindprozess:

package process.parent_child;

import Java.io.IOException;
import Java.util.Scanner;

public class ChildProc {


    private static class StdinListenerThread extends Thread {

        public void run() {
            int c;
            try {
                c = System.in.read();
                while ( c != -1 ) {
                    System.out.print(c);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("\nChild exits.");
            System.exit(0);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("I'm child process.");
        StdinListenerThread thread = new StdinListenerThread();
        thread.start();
        Thread.sleep(10000);
    }
}

Führen Sie diesen übergeordneten Prozess mit dem folgenden Befehl aus:

    Java process.parent_child.ParentProc

Du wirst sehen

    I'm parent.
    I'm child process.
    Parent exits.
    xmpy-mbp:bin zhaoxm$
    Child exits

Der untergeordnete Prozess wird sofort beendet, wenn der übergeordnete Prozess beendet wird.

5
xmpy

Wie Sie festgestellt haben, können Sie mit dem Betriebssystem dieses Problem umgehen. Erstellen Sie stattdessen eine Ressource, die von beiden Prozessen gemeinsam genutzt wird. Wenn das übergeordnete Element die Ressource abbricht, reagiert das untergeordnete Element mit dem Herunterfahren. Zum Beispiel:

Erstellen Sie einen Thread mit einem serverseitigen TCP/IP-Socket im Akzeptanzmodus für den übergeordneten Port an einem Port mit hoher Zufallszahl. Wenn das Kind startet, übergeben Sie die Portnummer als Parameter (Umgebungsvariable, Datenbankeintrag oder was auch immer). Lassen Sie es einen Thread erstellen und öffnen Sie den Socket. Die haben den Thread für immer auf der Buchse sitzen. Wenn die Verbindung jemals unterbrochen wird, müssen Sie das Kind beenden.

oder

Erstellen Sie einen Thread für das übergeordnete Element, das das Aktualisierungsdatum einer Datei ständig aktualisiert. (Wie oft hängt von der Granularität zwischen Kill und Herunterfahren ab.) Das untergeordnete Element verfügt über einen Thread, der die Aktualisierungszeit derselben Datei überwacht. Wenn es nach einem bestimmten Intervall nicht aktualisiert wird, wird es automatisch heruntergefahren.

3
jmucchiello

Bei einem einzelnen untergeordneten Prozess können Sie dies verwalten, indem Sie die untergeordnete/übergeordnete Beziehung invertieren. Siehe meine Antwort auf eine spätere Inkarnation dieser Frage.

2
dmckee

Wenn ich den Test durchgeführt habe, wird die PPID eines Kindes zu 1, wenn der Elternteil getötet wird. Wahrscheinlich können wir also alle Prozesse mit PPID = 1 beenden.

0
cache

Für Windows habe ich diesen Umfrage-Hack gefunden:

static int getPpid(int pid) throws IOException {
    Process p = Runtime.getRuntime().exec("C:\\Windows\\System32\\wbem\\WMIC.exe process where (processid="+pid+") get parentprocessid");
    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    br.readLine();
    br.readLine();
    String ppid= br.readLine().replaceAll(" ","");
    return Integer.parseInt(ppid);
}
static boolean shouldExit() {
    try {
        String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
        int ppid = getPpid(Integer.parseInt(pid));
        /* pppid */ getPpid(ppid);
    } catch (Exception e) {
        return true;
    } 
    return false;
}

Versuchen Sie, ein Abbruchsignal von dem übergeordneten Element an den untergeordneten Prozess zu senden, wenn das übergeordnete Element angehalten wird

0
Raxvan