Win32:匿名继承的管道不会在子进程退出时关闭

Ale*_*Max 0 c windows winapi

我一直试图使用匿名管道通过他们的stdin和stdout与生成的子进程通信,类似于这个例子.到目前为止,非常好 - 我通过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);
Run Code Online (Sandbox Code Playgroud)

我在示例和我的代码之间可以看到的唯一区别是我没有连接stderr - 我想保留它以进行fprintf调试.

从长远来看,我可能需要使用某种"心跳"消息,因为子进程可能变成一个僵尸并且完全活着并且保持它们的句柄打开但是从未读过stdin,这将把东西楔入不同的方式.但是,我想确保在我对Windows上的匿名管道的理解中没有遗漏任何东西.

RbM*_*bMm 7

你必须关闭midi_process_in_readermidi_process_out_writer在通话后CreateProcess().您的问题不是因为"继承的管道在子进程出口处没有关闭",这是因为您忘记在自己的进程中关闭管道.