我正在为进程管理库使用 I/O 完成端口(是的,这是有原因的)。您可以在这里找到我所说的内容的来源:https ://github.com/jcommon/process/blob/master/src/main/java/jcommon/process/platform/win32/Win32ProcessLauncher.java (采取查看第 559 和 1137 行——是的,该类需要重构和清理)。
我正在启动一个子进程并使用命名管道(不是匿名管道 b/c 我需要异步、重叠的 ReadFile()/WriteFile())来处理子进程的 stdout 和 stderr。这主要是实际工作。在测试中,我启动了 1000 个并发进程并监控它们的输出,确保它们发出正确的信息。通常,要么全部 1,000 个工作正常,要么其中 998 个工作正常,剩下的几个有问题。
这两个进程表明并非所有消息都被接收。我知道消息正在输出,但是该进程的处理 GetQueuedCompletionStatus() 的线程从读取中返回,并带有 ERROR_BROKEN_PIPE。
预期的行为是操作系统(或 C 库)将在进程退出时刷新标准输出缓冲区上的任何剩余字节。然后,我希望这些字节在出现管道损坏错误之前排队到我的 iocp 中。相反,这些字节似乎消失了,读取以 ERROR_BROKEN_PIPE 完成——在我的代码中,这导致它启动子进程的拆卸。
我编写了一个简单的应用程序来测试和找出行为(https://github.com/jcommon/process/blob/master/src/test/c/stdout-1.c)。此应用程序禁用 stdout 上的缓冲,因此应立即有效地刷新所有写入。在我的测试中使用该程序会产生与启动“cmd.exe /c echo hi”相同的问题。无论如何,当进程退出时,应用程序(或操作系统?)不应该刷新标准输出上的任何剩余字节吗?
源代码是 Java,使用直接映射的 JNA,但 C/C++ 工程师应该很容易理解。
感谢您的任何帮助,您可以提供!