Java 当父进程退出时,如何使子进程退出?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/269494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:16:09  来源:igfitidea点击:

How can I cause a child process to exit when the parent does?

javaprocess

提问by Alex

I am launching a child process with ProcessBuilder, and need the child process to exit if the parent process does. Under normal circumstances, my code is stopping the child properly. However, if I cause the OS to kill the parent, the child will continue running.

我正在使用 ProcessBuilder 启动一个子进程,如果父进程退出,则需要子进程退出。在正常情况下,我的代码正确地停止了孩子。但是,如果我让操作系统杀死父进程,子进程将继续运行。

Is there any way to "tie" the child process to the parent, such that it'll exit when the parent is killed?

有没有办法将子进程“绑定”到父进程,这样它会在父进程被杀死时退出?



Similar questions:

类似问题:

采纳答案by sblundy

There is no tie between a child process and its parent. They may know each others process ID, but there's no hard connection between them. What you're talking about a orphan process. And it's an OS level concern. Meaning any solution is probably platform dependent.

子进程与其父进程之间没有联系。它们可能知道彼此的进程 ID,但它们之间没有硬连接。你在说什么孤儿进程。这是操作系统级别的问题。这意味着任何解决方案都可能依赖于平台。

About the only thing I can think of is to have the child check its parents status periodically, exiting if the parent's shutdown. I don't think this would be all that reliable though.

我唯一能想到的就是让孩子定期检查其父母的状态,如果父母关机则退出。不过,我认为这不会那么可靠。

回答by sblundy

Try to send a kill signal to the child process from the parent when the parent stops

尝试在父进程停止时从父进程向子进程发送终止信号

回答by Greg Case

While you cannot protect against a hard abort (e.g. SIGKILL on Unix), you can protect against other signals that cause your parent process to shut down (e.g. SIGINT) and clean up your child process. You can accomplish this through use of shutdown hooks: see Runtime#addShutdownHook, as well as a related SO question here.

虽然您无法防止硬中止(例如 Unix 上的 SIGKILL),但您可以防止导致您的父进程关闭(例如 SIGINT)并清理您的子进程的其他信号。您可以通过使用关闭挂钩来完成此操作:请参阅Runtime#addShutdownHook以及相关的 SO 问题here

Your code might look something like this:

您的代码可能如下所示:

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

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

Runtime.getRuntime().addShutdownHook(closeChildThread); 

回答by dmckee --- ex-moderator kitten

For a single child processes you can manage this by inverting the child/parent relationship. See my answerto a later incarnation of this question.

对于单个子进程,您可以通过反转子/父关系来管理它。请参阅对这个问题后来的化身的回答。

回答by jmucchiello

As you've found the operating system allows you to get around this issue. Instead, create a resource shared by both processes. When the parent aborts the resource, the child reacts by shutting down. For example:

正如您发现的那样,操作系统允许您解决这个问题。相反,创建一个由两个进程共享的资源。当父级中止资源时,子级的反应是关闭。例如:

Create a thread with an server-side TCP/IP socket in accept mode on the parent on a random high number port. When the child starts, pass the port number as a parameter (environment variable, database entry, whatever). Have it create a thread and open that socket. The have the thread sit on the socket forever. If the connection ever drops, have the child exit.

在随机高数端口上的父级上创建一个具有接受模式的服务器端 TCP/IP 套接字的线程。当子进程启动时,将端口号作为参数(环境变量、数据库条目等)传递。让它创建一个线程并打开那个套接字。让线程永远坐在套接字上。如果连接中断,请让孩子退出。

or

或者

Create a thread on parent that continually updates the update date on a file. (How often depends on how much granularity between kill and shutdown you need.) The child has a thread that monitors the update time of the same file. If it doesn't update after a specific interval, automatically shutdown.

在父级上创建一个线程,不断更新文件的更新日期。(多久取决于您需要在kill 和shutdown 之间有多大的粒度。)子进程有一个线程来监控同一个文件的更新时间。如果在特定时间间隔后没有更新,则自动关闭。

回答by tomkri

You can simply start a thread reading from System.in in the child process. If you are not writing to stdin of your child, nobody else will do and the thread will block "forever". But you will get an EOF (or an exception), if the parent process is killed or dies otherwise. So you can shutdown the child as well. (Child process started with java.lang.ProcessBuilder)

您可以简单地在子进程中启动一个从 System.in 读取的线程。如果您没有写入孩子的标准输入,其他人不会这样做,并且该线程将“永远”阻塞。但是,如果父进程被杀死或以其他方式死亡,您将获得 EOF(或异常)。所以你也可以关闭孩子。(子进程以 java.lang.ProcessBuilder 开始)

回答by cache

As I tested, if the parent is killed, then the ppid of a child will become 1. So probably we can kill any processes that have ppid = 1.

正如我测试的那样,如果父进程被杀死,那么子进程的 ppid 将变为 1。所以我们可能可以杀死任何 ppid = 1 的进程。

回答by Juan Pablo Fernandez

For windows, I came up with this polling hack:

对于 Windows,我想出了这个轮询黑客:

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;
}

回答by xmpy

Provide a hacker way which is similar with the answer from @tomkri and also provide the demo code.

提供与@tomkri 的答案类似的黑客方式,并提供演示代码。

If your child process do not need use input stream, just redirect child process input stream to its parent process's input stream. Then add a thread in child to always read input stream and when this thread can not read anything from input stream, this child process exits. So the parent process exits -> parent's input stream does not exist -> child's input stream does not exist -> child process exits.

如果您的子进程不需要使用输入流,只需将子进程输入流重定向到其父进程的输入流。然后在 child 中添加一个线程来始终读取输入流,当该线程无法从输入流中读取任何内容时,该子进程退出。所以父进程退出->父进程的输入流不存在->子进程的输入流不存在->子进程退出。

Here is the demo code all in Java.

这是所有在 Java 中的演示代码。

Parent Process:

父进程:

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.");
    }
}

Child Process:

子进程:

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);
    }
}

After run this parent process by the following command:

通过以下命令运行此父进程后:

    java process.parent_child.ParentProc

You will see

你会看见

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

Child process exits immediately when parent process exits.

当父进程退出时,子进程立即退出。