开发者

broken pipe in win32 (WinAPI)

I have followed the example here for reading from a pipe, but ReadFile fails and GetLastError() shows me that the pipe is broken.

I have created and used (successfully) a pipe earlier in the program, but I closed all the handles and used entirely new variables for the new pipe just to be sure.

Any ideas why this doesn't work?

HANDLE g_hChildStd_OUT_Rd2 = NULL;
HANDLE g_hChildStd_OUT_Wr2 = NULL;
SECURITY_ATTRIBUTES saAttr2; 
STARTUPINFO si2;
PROCESS_INFORMATION pi2;

ZeroMemory( &si2, sizeof开发者_JAVA百科(si2) );
si2.cb = sizeof(si2);
ZeroMemory( &pi2, sizeof(pi2) );
//create pipe
saAttr2.nLength = sizeof(SECURITY_ATTRIBUTES); 
saAttr2.bInheritHandle = TRUE; 
saAttr2.lpSecurityDescriptor = NULL; 
CreatePipe(&g_hChildStd_OUT_Rd2, &g_hChildStd_OUT_Wr2, &saAttr2, 0);
//create child process
bSuccess = FALSE;
memset(szCmdLine, 0, MAX_PATH);
sprintf(szCmdLine, "ffmpeg.exe -i output.mp3");
ZeroMemory( &pi2, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &si2, sizeof(STARTUPINFO) );
si2.cb = sizeof(STARTUPINFO); 
si2.hStdOutput = g_hChildStd_OUT_Wr2;
si2.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2);
//read from pipe
CloseHandle(g_hChildStd_OUT_Wr2);
memset(chBuf, 0, BUFSIZE);
for (;;) 
{ 
  bSuccess = ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE, &dwRead, NULL);
  [bSuccess is 0 and GetLastError() returns error 109]
  ........


"Broken pipe" is a normal error when the other end closes the pipe. In your case, this either means there is no "other end", or the other application hasn't written anything to its stdout. I've modified your code to be a compilable test case – there are two cases in which ReadFile fails without having read any data for me:

  • CreateProcess failed. I've added an assert so that problem will be recognizable. It would of course result in a broken pipe.
  • The process does not write anything to standard output. It might instead write to its standard error stream. I've redirected stderr to the pipe as well, and as my echo example shows, this will receive both streams on the other end of the pipe now.

Code:

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

#define BUFSIZE 200

int main(void)
{
    BOOL bSuccess;
    char 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);
    sprintf(szCmdLine, "cmd /c echo output && echo error>&2");
    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 (;;) 
    { 
        bSuccess = ReadFile( g_hChildStd_OUT_Rd2, chBuf, BUFSIZE, &dwRead, NULL);
        printf("%d %lu 0x%08lx\n", bSuccess, dwRead, GetLastError());
        if (bSuccess)
            printf("\t'%*s'\n", (int)dwRead, chBuf);
        else
            break;
    }
    return 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜