![](/img/trans.png)
[英]Named pipe: ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE
[英]ERROR_BROKEN_PIPE cannot read process output produced before process termination
我在Win32中有一個簡單的過程重定向例程。 這里的問題是,如果我在子進程stdout的讀取之間放置一個Sleep,則當我在睡眠時終止該進程時,我只會錯過輸出ERROR_BROKEN_PIPE的管道中的最后一個字節。 看來,一旦子進程終止,它的管道和關聯的句柄就會關閉,所有待處理的東西都會被丟棄。 唯一的解決方案似乎是盡可能快地從管道中讀取File,但是由於軟件的設計,這對我來說不只是一個問題。
int _tmain(int argc, _TCHAR* argv[])
{
BOOL bSuccess;
WCHAR szCmdLine[MAX_PATH];
char chBuf[BUFSIZE];
DWORD dwRead;
HANDLE g_hChildStd_OUT_Rd2 = NULL;
HANDLE g_hChildStd_OUT_Wr2 = NULL;
SECURITY_ATTRIBUTES saAttr2;
STARTUPINFO si2;
PROCESS_INFORMATION pi2;
ZeroMemory( &si2, sizeof(si2) );
si2.cb = sizeof(si2);
ZeroMemory( &pi2, sizeof(pi2) );
//create pipe
saAttr2.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr2.bInheritHandle = TRUE;
saAttr2.lpSecurityDescriptor = NULL;
assert(CreatePipe(&g_hChildStd_OUT_Rd2, &g_hChildStd_OUT_Wr2, &saAttr2, 0));
//create child process
bSuccess = FALSE;
memset(szCmdLine, 0, MAX_PATH);
wsprintf(szCmdLine, L"c:\\myprocess.exe");
ZeroMemory( &pi2, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &si2, sizeof(STARTUPINFO) );
si2.cb = sizeof(STARTUPINFO);
si2.hStdOutput = g_hChildStd_OUT_Wr2;
si2.hStdError = g_hChildStd_OUT_Wr2; // also add the pipe as stderr!
si2.dwFlags |= STARTF_USESTDHANDLES;
assert(CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2));
//read from pipe
CloseHandle(g_hChildStd_OUT_Wr2);
memset(chBuf, 0, BUFSIZE);
for (;;)
{
DWORD dwRead = 0;
DWORD bytes = 0;
if (!PeekNamedPipe(g_hChildStd_OUT_Rd2,NULL,NULL,NULL,&bytes,NULL)) {
//printf("Peek named pipe failed!");
break;
}
if (bytes != 0) {
if (!ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE, &dwRead, NULL))
{
printf("EOF!!\n");
break;
}
else {
chBuf[dwRead] = 0;
printf("%s", chBuf);
}
} else {
Sleep(5000);
}
}
while(1) {
Sleep(1000);
printf("Lopp!\n");
}
return 0;
}
有什么提示嗎? 有沒有一種方法可以像在POSIX中一樣保持進程直到讀取其管道?
謝謝!
我認為問題不存在。
您的代碼中確實有一些問題。 許多是未成年人:您對si2和pi2進行了兩次初始化(無害),您有一個無限循環,因此您的編將永無止境(我假設您是Ctrl-C ...),您正在混合_tmain
和WCHAR(應為wmain
和WCHAR
或_tmain
和TCHAR
),但如果您執行unicode構建,則可以。
一種更為嚴重: chBuf
大小為BUFSIZE
,您chBuf
可以讀取BUFSIZE
字符(直到此處為止)。 但是,如果您確實讀取了BUFSIZE個字符,則dwRead
為BUFSIZE
並且在下一行您將有緩沖區溢出
chBuf[dwRead] = 0; // buffer overflow if BUFSIZE chars have been read !
我只用:
if (!ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE - 1, &dwRead, NULL))
並且程序正常運行。
順便說一句:在關閉子進程的所有句柄之前,系統都會知道子進程(即使已終止)……並且您在pi2.hProcess
也擁有該子進程的句柄。
當然,我不能使用c:\\\\myprocess.exe
並使用cmd /c dir
進行測試。 因此,如果上面的修復是不夠的嘗試使用同一個孩子像我一樣,因為這個問題可能來自myprocess.exe
即開始用NULL hStdInput
好的,僅供參考,我想分享我的經驗以及如何解決該問題。 可能是我生成的子進程中有問題,但是從我的觀察中,如果我以非阻塞模式調用Read,那么只有在PeekNamedPipe之后,沒有什么可以阻止該進程被釋放,即使我保持對管道的引用。 我已經解決了啟動另一個線程的問題,該線程確實阻止了管道描述符上的Read,並且我失去了最后一個字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.