【发布时间】:2017-02-22 02:32:39
【问题描述】:
我一直在尝试使用匿名管道通过它们的标准输入和标准输出与衍生的子进程进行通信,类似于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 调试。
从长远来看,我可能需要使用某种“心跳”消息,因为子进程可能会变成僵尸并完全活着并保持其句柄打开但永远不会读取标准输入,这会楔入事情以不同的方式。但是,我想确保在我对 Windows 上的匿名管道的理解中没有遗漏一些东西。
【问题讨论】: