0

我正在为进程管理库使用 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++ 工程师应该很容易理解。

感谢您的任何帮助,您可以提供!

4

1 回答 1

0

您确定非零 ioSize 不会发生损坏的管道错误吗?如果 ioSize 不为零,那么您应该处理读取的数据并注意文件现在已关闭。

执行此操作的我的 C++ 代码基本上忽略ERROR_BROKEN_PIPEERROR_HANDLE_EOF只是等待下一次读取尝试失败并出现上述错误之一,或者当前读取完成并读取零字节。有问题的代码适用于文件和管道,在运行您描述的那种测试时,我从未见过您描述的问题。

于 2013-07-04T16:51:56.803 回答