匿名管道:当子进程被杀死时,父进程中的 ReadFile 继续等待

Posted

技术标签:

【中文标题】匿名管道:当子进程被杀死时,父进程中的 ReadFile 继续等待【英文标题】:Anonymous pipes: ReadFile in parent process keeps on waiting when the child process is killed 【发布时间】:2016-12-27 16:08:18 【问题描述】:

我有一个程序,其中父进程派生出一个子进程,然后与之通信。

父进程是 VB 应用程序,子进程是 C# 控制台应用程序。

父进程(暂时删除错误处理):

Private Function InitialieExtConversionProcess() As Boolean

Dim lResult As Long
Dim SA As SECURITY_ATTRIBUTES
Dim sInfo As STARTUPINFO
Dim sCommandLine As String

SA.bInheritHandle = True

'Create the pipe that Hyperspace will write to
lResult = CreatePipe(m_pipeOut.hReadPipe, m_pipeOut.hWritePipe, SA, 0)

'Ensure that the read handle is not inherited
lResult = SetHandleInformation(m_pipeOut.hReadPipe, HANDLE_FLAG_INHERIT, 0)


'Create the pipe that Hyperspace will read from
lResult = CreatePipe(m_pipeIn.hReadPipe, m_pipeIn.hWritePipe, SA, 0)

'Ensure that the write handle is not inherited
lResult = SetHandleInformation(m_pipeIn.hWritePipe, HANDLE_FLAG_INHERIT, 0)

'Create the external process
sCommandLine = "some_path\ExtProcess.exe"
sInfo.hStdInput = m_pipeIn.hReadPipe
sInfo.hStdError = m_pipeOut.hWritePipe
sInfo.hStdOutput = m_pipeOut.hWritePipe
sInfo.dwFlags = STARTF_USESTDHANDLES
lResult = CreateProcess(0, sCommandLine, 0, 0, 1, CREATE_NO_WINDOW, 0, 0,   sInfo, m_pInfo)

InitialieExtConversionProcess = True

End Function

然后我使用 WriteFile 和 ReadFile 对子进程进行写入和读取

lResult = WriteFile(m_pipeIn.hWritePipe, sOutput, Len(sOutput), 0, 0)
...
lResult = ReadFile(m_pipeOut.hReadPipe, sInput, Len(sInput), 0, ByVal 0)

子进程(C# 控制台应用程序):

IntPtr hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
IntPtr hInput = GetStdHandle(STD_INPUT_HANDLE);              
AnonymousPipeClientStream pipeClientRead = new     AnonymousPipeClientStream(PipeDirection.In, hInput.ToString());
AnonymousPipeClientStream pipeClientWrite = new AnonymousPipeClientStream(PipeDirection.Out, hOutput.ToString());

arr = new byte[300];
pipeClientRead.Read(arr, 0, 300);
...
arr = Encoding.ASCII.GetBytes(strResult);
pipeClientWrite.Write(arr, 0, arr.Length);
pipeClientWrite.Flush();

通信在这里按预期工作。我能够成功地读写。

当父进程关闭时,子进程中的Read操作返回false。但是当子进程杀死自己时(如下所示),父进程继续等待 ReadFile。为什么会这样?

arr = new byte[300];
pipeClientRead.Read(arr, 0, 300);
--->Environment.exit(1);<----
arr = Encoding.ASCII.GetBytes(strResult);
pipeClientWrite.Write(arr, 0, arr.Length);
pipeClientWrite.Flush();

我密切关注这个 msdn 示例: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx

【问题讨论】:

【参考方案1】:

我找到了错误的地方。

创建后需要关闭子进程的句柄。

lResult = CreateProcess(0, sCommandLine, 0, 0, 1, CREATE_NO_WINDOW, 0, 0,   sInfo, m_pInfo)
CloseHnadle(m_pipeIn.hReadPipe)
CloseHandle(m_pipeOut.hWritePipe)

【讨论】:

以上是关于匿名管道:当子进程被杀死时,父进程中的 ReadFile 继续等待的主要内容,如果未能解决你的问题,请参考以下文章

当父进程被杀死时,使用 fork() 创建的子进程是不是会自动被杀死?

进程管理

如何使用子进程模块杀死(或避免)僵尸进程

QProcess::startDetached shell 在父进程死亡时被杀死,如果父进程是一个 systemd 服务

阻止写入标准输出

如何在父进程被杀死/完成时保持子进程处于活动状态(在 Windows 中)