Process.Start的stdout和stderr的缓冲区大小是多少?

7
我正在尝试查找这些信息。 显然,微软没有提供可靠地读取进程stdoutstderr的代码,而不会出现死锁、异常和其他问题。
死锁问题 http://www.codeducky.org/process-handling-net/ 较不明显的问题是死锁。所有三个进程流(输入、输出和错误)在内容缓冲区方面都有限制。如果内部缓冲区填满,则正在写入流的人将被阻塞。例如,在此代码中,我们在进程退出后才从输出和错误流中读取数据。这意味着我们可能会发现外部进程用尽其错误缓冲区的情况。在这种情况下,外部进程将阻塞写入标准错误,而我们的.NET应用程序将阻塞读取标准输出的末尾。因此,我们陷入了死锁!
没有可靠的代码
有一个获得了265次赞的答案,但我不打算使用它,因为它会出现ObjectDisposeException并需要超时:
ProcessStartInfo hanging on "WaitForExit"? Why? 在它被发现会导致ObjectDisposeException之前,它可能已经获得了赞。
死锁的机会有多大?
我想知道进入死锁状态的机会有多大。 为此,我需要知道Windows 7下stderr和stdout的缓冲区大小。
如何找到它们? 我以为我可以打印几个文件,看看哪个文件尺寸大概会导致问题,但在Windows 7下没有这个命令。我甚至尝试使用git cat-file,但它的文档很差,没有使用示例,也没有人回答有关它的问题:https://stackoverflow.com/questions/43203902/how-to-git-cat-file-a-file-in-current-dir

1
看起来缓冲区大小可能是4千字节 - 请参见第2165和2169行。 - ProgrammingLlama
你提到的第一篇文章解释了如何避免死锁(异步从两个流中读取)。此外,还有一个名为type的命令,与cat大致相似。 - Evk
2
这些缓冲区存在于您启动的进程中,而不是.NET和Process类中。实际大小完全取决于用于构建程序的工具链,4096字节是非常典型的值。但程序员可能已经更改了它,setvbuf()是用于执行此操作的样板C库函数。如果您想指责某人,那么您必须将其瞄准Ken Thompson,I/O重定向是一个可怕的破损功能,本应该留在Unix中。 - Hans Passant
1
答案中的代码确实有问题,但是可以修复,并且在另一个回答中有修复方法。此外,第一个链接文章中提到的不是同一段代码。我建议您尝试第一篇文章中看起来合理的代码,甚至可以尝试他们建议的库(MediallionShell)。 - Evk
并且通过在页面上搜索“ObjectDisposed”可以轻松找到-它是该字符串的仅有两个实例之一。不要期望所有东西都被白捡到手。 - Damien_The_Unbeliever
显示剩余6条评论
2个回答

5
约翰的评论是正确的,这段代码硬编码了4096个字节。 https://github.com/Microsoft/referencesource/blob/master/System/services/monitoring/system/diagnosticts/Process.cs
    if (startInfo.RedirectStandardInput) {
            standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), Console.InputEncoding, 4096);
            standardInput.AutoFlush = true;
        }
        if (startInfo.RedirectStandardOutput) {
            Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Console.OutputEncoding;
            standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
        }
        if (startInfo.RedirectStandardError) {
            Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Console.OutputEncoding;
            standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);

我进行了测试,运行了cmd.exe type path\to\file.html命令,但它只输出了部分内容。因此,我编写了一行Ruby脚本来打开文件并将其输出到标准输出。对于大小为4373字节的文件,它失败了,而对于大小为3007字节的文件,它可以正常工作。它会卡住,死锁。

我认为微软的进程处理真是太可悲了。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接