如何在后代仍然存在时关闭 Windows 上的 Java 子进程 stdout 文件描述符

发布于 2024-10-27 11:57:37 字数 1217 浏览 0 评论 0原文

给定一个简单的批处理文件 c1.bat,包含:

start notepad 1> nul 2> nul
exit

和一个 Java 程序:

import java.io.InputStream;

public class ProcessTest {

    public static void main(String[] args) throws Exception {
        ProcessBuilder b = new ProcessBuilder();
        b.command("c1.bat");
        Process p = b.start();
        new Thread(new ProcDrain(p)).start();
        System.out.println("Parent process finished: " + p.waitFor());
    }

    private static class ProcDrain implements Runnable {
        private final Process p;

        private ProcDrain (Process p) {
            this.p = p;
        }

        @Override
        public void run() {
            try {
                InputStream in = p.getInputStream();
                while (in.read() >= 0) { }
                System.out.println("Inputstream drainer finished");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

第一个执行 c1.bat 的进程立即结束并生成另一个进程(记事本)。然而,drainer 线程在 read() 调用中被阻塞,并且在记事本关闭之前不会终止。这表明记事本保持打开原始进程的标准输出文件描述符,尽管批处理文件已重定向它。

批处理文件是否有某种方法可以关闭 stdout/stderr 文件描述符,以便一旦生成的进程实际退出,drainer 线程就不会在 read() 上阻塞?

Given a simple batch file, c1.bat, containing:

start notepad 1> nul 2> nul
exit

and a Java program:

import java.io.InputStream;

public class ProcessTest {

    public static void main(String[] args) throws Exception {
        ProcessBuilder b = new ProcessBuilder();
        b.command("c1.bat");
        Process p = b.start();
        new Thread(new ProcDrain(p)).start();
        System.out.println("Parent process finished: " + p.waitFor());
    }

    private static class ProcDrain implements Runnable {
        private final Process p;

        private ProcDrain (Process p) {
            this.p = p;
        }

        @Override
        public void run() {
            try {
                InputStream in = p.getInputStream();
                while (in.read() >= 0) { }
                System.out.println("Inputstream drainer finished");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

The first process, which executes c1.bat, ends promptly having spawned another process (notepad). The drainer thread however is blocked in the read() call, and does not terminate until notepad is closed. This suggests that notepad is holding open the stdout file descriptor of the original process, despite the batch file having redirected it.

Is there some way for the batch file to close the stdout/stderr file descriptors such that the drainer thread will not block on read() once the spawned process has actually exited?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文