这是我的场景:
- 进程 A 产生子进程 B 并旋转线程以耗尽 B 的输出。
- 进程 B 生成守护进程 C 并排出其输出。
- 进程 B 完成,守护进程仍然存在。
- 进程 A 发现进程 B 通过 process.waitFor() 退出。但是,它一直在读取进程 B 的输入流。这是因为 B 已经启动了一个守护进程。输入流仅在进程 C 退出时接收 EOF。
这只发生在 Windows 上。我正在使用 ProcessBuilder。这是我想出的解决方案,我想听听您的反馈,因为没有我真正喜欢的解决方案:
- 我可以使用 jna 来生成守护进程 C。这样我可以创建一个“足够分离”的进程,并且进程 A 不会卡在从 B 中排出流。它有效,但我不太热衷于该解决方案,因为这意味着一些本机代码(还有很多,因为我热衷于使用输入)。一些如何通过 JNA 来实现的灵感在这里:http: //yajsw.sourceforge.net(但是它包含的东西不仅仅是进程启动)。
- 在 jre7 上运行。Jdk7 为 ProcessBuilder 带来了一些新的好处,例如,inheritIO() 也解决了我的问题。显然,当打开inheritIO() 时,我可以简单地关闭守护进程C 中的所有流(无论如何我都会这样做,因为它是一个守护进程),这就解决了问题。但是,我需要在 jre5+ 上运行
- 在生成守护进程 C之前关闭进程 B 中的 System.out 和 System.err 。同样,它解决了问题,但我确实需要这些流在进程 B 中工作,因为我向它们编写有用的东西。不好。我希望我可以通过在 B 和 C 之间放置某种引导过程来利用这个特性,但这并没有解决问题。
- 我在linux上没有这个问题,所以我只能在linux上运行吗?不,我不能。
- 使进程 A 以非阻塞方式排出进程 B 的输出。这有点工作,但它不方便。例如 inputStream.read() 是不可中断的。我可以使用 inputStream.available() 但它不区分 EOF 和零字节可用。因此,只有当进程 A 对 B 的输出 EOF 不感兴趣时,该解决方案才是好的。此外,这个解决方案似乎更占用 CPU 资源,而且通常......感觉很尴尬,而且不是真正的防弹。
- 在 --dry-run 模式下运行进程 C,它只是检查它是否可以启动。它尝试启动、发送欢迎消息并退出。它不再长时间运行,因此不会阻塞读取。进程 B 可以获得足以启动 C 的信心,并且我们可以使用相对简单的 JNA 代码来生成分离的进程而不消耗其输出(正是输出的消耗使 JNA 相关的代码变得混乱和重量级)。唯一的问题是我们不再使用进程的 C 输出,但可以通过让 C 写入进程 B 可以使用的众所周知的文件来解决。这个解决方案更像是一个大而丑陋的解决方法,但对我们来说是可行的。无论如何,我们目前正在尝试解决方案 1)。
我真的很感激任何提示!