我正在为进程管理库使用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。这主要是实际工作。在测试中,我启动1,000个并发进程并监视其输出,确保它们发出正确的信息。通常要么全部1000个工作正常,要么998个工作正常,留下一些有问题。
这几个过程显示并非所有消息都被接收。我知道正在输出消息,但该进程的处理GetQueuedCompletionStatus()的线程从使用ERROR_BROKEN_PIPE的读取返回。
预期的行为是OS(或C libs)将在进程退出时刷新stdout缓冲区上的任何剩余字节。然后我会期望在获得管道损坏错误之前将这些字节排队到我的iocp。相反,这些字节似乎消失了,并且读取以ERROR_BROKEN_PIPE完成 - 这在我的代码中导致它启动子进程的拆解。
我编写了一个简单的应用程序来测试并找出行为(https://github.com/jcommon/process/blob/master/src/test/c/stdout-1.c)。此应用程序禁用stdout上的缓冲,因此应立即有效地刷新所有写入。在我的测试中使用该程序会产生与启动“cmd.exe / c echo hi”相同的问题。无论如何,当进程退出时,应用程序(或OS?)是否应该刷新stdout上的任何剩余字节?
源代码是Java,使用直接映射的JNA,但C / C ++工程师应该很容易理解。
感谢您提供的任何帮助!
答案 0 :(得分:0)
您确定非零ioSize没有发生损坏的管道错误吗?如果ioSize不为零,那么您应该处理已读取的数据,并注意文件现在已关闭。
执行此操作的我的C ++代码基本上忽略ERROR_BROKEN_PIPE
和ERROR_HANDLE_EOF
,只是等待下一次读取尝试失败并出现上述错误之一,或者当前读取完成时读取零字节。有问题的代码适用于文件和管道,我从未见过您在运行所描述的测试类型时所描述的问题。