我一直试图使用匿名管道通过他们的stdin和stdout与生成的子进程通信,类似于this example . 到目前为止,这么好 - 我通过WriteFile()与它通信,我通过PeekNamedPipe()和ReadFile()从它读取数据 . 生活很好 .
然而,我遇到了令人痛苦的事情 - 当子进程意外关闭时,对WriteFile()的父进程调用似乎永远不会返回任何类型的失败状态,表明管道已关闭,并且我的父进程继续愉快地继续写入数据直到我溢出管道的内部缓冲区并永远阻塞 .
我的设置代码如下所示:
// Set up pipes
SECURITY_ATTRIBUTES sec_attrs;
memset(&sec_attrs, 0, sizeof(SECURITY_ATTRIBUTES));
sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
sec_attrs.bInheritHandle = TRUE;
sec_attrs.lpSecurityDescriptor = NULL;
if (!CreatePipe(&midi_process_in_reader, &midi_process_in_writer, &sec_attrs, 0))
{
DEBUGOUT("Could not initialize midiproc stdin");
return false;
}
if (!SetHandleInformation(midi_process_in_writer, HANDLE_FLAG_INHERIT, 0))
{
DEBUGOUT("Could not disinherit midiproc stdin");
return false;
}
if (!CreatePipe(&midi_process_out_reader, &midi_process_out_writer, &sec_attrs, 0))
{
DEBUGOUT("Could not initialize midiproc stdout/stderr");
return false;
}
if (!SetHandleInformation(midi_process_out_reader, HANDLE_FLAG_INHERIT, 0))
{
DEBUGOUT("Could not disinherit midiproc stdin");
return false;
}
// Launch the subprocess
PROCESS_INFORMATION proc_info;
memset(&proc_info, 0, sizeof(proc_info));
STARTUPINFO startup_info;
memset(&startup_info, 0, sizeof(startup_info));
startup_info.cb = sizeof(startup_info);
startup_info.hStdInput = midi_process_in_reader;
startup_info.hStdOutput = midi_process_out_writer;
startup_info.dwFlags = STARTF_USESTDHANDLES;
BOOL ok = CreateProcess(TEXT(module), TEXT(cmdline), NULL, NULL, TRUE,
CREATE_NEW_CONSOLE, NULL, NULL, &startup_info, &proc_info);
我可以在示例和我的代码之间看到的唯一区别是我没有连接stderr - 我想保留它以进行fprintf调试 .
从长远来看,我可能需要使用某种“心跳”消息,因为子进程可能变成一个僵尸并且完全活着并且保持它们的句柄打开但是从不读取stdin,这将把东西楔入不同的方式 . 但是,我想确保在我对Windows上的匿名管道的理解中没有遗漏任何东西 .
1 回答
调用
CreateProcess()
后,您必须关闭midi_process_in_reader
和midi_process_out_writer
. 您的问题不是因为"inherited pipes don't close on subprocess exit",而是因为您忘记在自己的进程中关闭管道 .