0

In my app I'm using Unnamed Pipes as an output of MiniDumpWriteDump function - i don't want actually create the file, just write MiniDump to memory buffer.

Method to read bytes from pipe is called from another thread. When I call MiniDumpWriteDump function, the ReadFile and MiniDumpWriteDump function never returns.

I've tried to check whether it is problem with bad handles, or too small size of pipes, but when I use simple WriteFile function, everything seems fine (even if pipe size is smaller than written string).

Here is piece of my code:

void CCrashHandler::PipeDump()
{
    ...
    m_ePipeEnd = CreateEvent( 
      NULL, // default security attribute
      TRUE, // manual reset event 
      TRUE, // initial state = signaled 
      NULL);   // unnamed event object 
    m_ePipeStart = CreateEvent( 
      NULL, // default security attribute
      TRUE, // manual reset event 
      TRUE, // initial state = signaled 
      NULL);   // unnamed event object 

    if(m_ePipeEnd == NULL || m_ePipeStart == NULL)
    {

        return;
    }

    // Create pipe handles
    HANDLE readPipe, writePipe;
    if(!CreatePipe(&readPipe, &writePipe, NULL, PIPESIZE))
    {

        return;
    }

    // Load dbghelp.dll
    hDbgHelp = LoadLibrary(_T("dbghelp.dll"));
    if(hDbgHelp==NULL)
    {
        // Error - couldn't load dbghelp.dll

        return;
    }

    // Write minidump to the file
    mei.ThreadId = GetCurrentThreadId();
    mei.ExceptionPointers = pExcPtrs;
    mei.ClientPointers = FALSE;
    mci.CallbackRoutine = NULL;
    mci.CallbackParam = NULL;

    typedef BOOL (WINAPI *LPMINIDUMPWRITEDUMP)(
        HANDLE hProcess, 
        DWORD ProcessId, 
        HANDLE hFile, 
        MINIDUMP_TYPE DumpType, 
        CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, 
        CONST PMINIDUMP_USER_STREAM_INFORMATION UserEncoderParam, 
        CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

    LPMINIDUMPWRITEDUMP pfnMiniDumpWriteDump = 
        (LPMINIDUMPWRITEDUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
    if(!pfnMiniDumpWriteDump)
    {   
        // Bad MiniDumpWriteDump function
        // Close handles
        CloseHandle(readPipe);
        CloseHandle(writePipe);

        return;
    }
    HANDLE hProcess   = GetCurrentProcess();
    DWORD dwProcessId = GetCurrentProcessId();
    DWORD  dwThreadId = 0;

    ResetEvent(m_ePipeStart);
    ResetEvent(m_ePipeEnd);
    // Create thread to read from pipe
    HANDLE hThreadRead = CreateThread( 
            NULL,              // no security attribute 
            PIPESIZE*2,      // default stack size 
            PipeThreadRead,     // thread proc
            (LPVOID)readPipe,   // thread parameter 
            0,                // not suspended 
            &dwThreadId);       // returns thread ID 

    // Signal start of writing to a pipe
    BOOL bRet = SetEvent(m_ePipeStart);
    BOOL bWriteDump = pfnMiniDumpWriteDump(
        hProcess,
        dwProcessId,
        writePipe,
        m_MiniDumpType,
        &mei,
        NULL,
        &mci);
    /*
           This one works fine!
    wchar_t bufor[100];
    int len=wsprintf(bufor,_T("Hello Client From Server (msg #)\n"));

    bRet=WriteFile(writePipe,bufor,len*sizeof(wchar_t),&m_wPipeBytes,NULL);
    */

    Sleep(100);
    // Signal end of writing to a pipe
    bRet = SetEvent(m_ePipeEnd);

    if(!bWriteDump)
    {   
        // Error writing dump.
        // Close handles
        CloseHandle(readPipe);
        CloseHandle(writePipe);

        DWORD nOSError = ::GetLastError();
        wchar_t buf[1024];
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, nOSError, LANG_USER_DEFAULT, buf, 1024, NULL);

        return;
    }
    //bRet = TerminateThread(hThreadRead, -1);
    CloseHandle(writePipe);
    CloseHandle(readPipe);
    ...
}
// Functions, which handles reading from pipe
DWORD WINAPI CCrashHandler::PipeThreadRead(LPVOID szParams)
{
    HANDLE hPipe = (HANDLE) szParams;
    DWORD sum = 0;
    m_pPipeRead = NULL;
    while(1)
    {
        if(WaitForSingleObject(m_ePipeStart, 5000)==WAIT_OBJECT_0)
            break;
    }
    BYTE buf[PIPESIZE];

    while(1)
    {
        memset(buf, 0, PIPESIZE);

        DWORD dwRead;

        if( ReadFile(hPipe,buf,10,&dwRead,NULL) )
        {
            if(m_pPipeRead == NULL)
            {
                m_pPipeRead = (BYTE*) malloc(dwRead);
            }else
            {
                m_pPipeRead = (BYTE*) realloc( m_pPipeRead, dwRead + sum );
            }

            memcpy(m_pPipeRead+sum, buf, dwRead);

            sum+=dwRead;
        }
        if(WaitForSingleObject(m_ePipeEnd, 0)==WAIT_OBJECT_0)
            break;
    }
    return 1;
}
filipbe
  • 165
  • 15
  • 1
    I think that MiniDumpWriteDump must stop all threads in the process to get static process dump. So, pipe read thread is stopped, which effectively stops MiniDumpWriteDump call. – Alex F Dec 12 '12 at 14:35
  • Yup, that's it. You in general ought to call MiniDumpWriteDump from another process so corrupted state of a failed process doesn't cause trouble. – Hans Passant Dec 12 '12 at 14:51
  • In most cases MiniDumpWriteDump call from the same process is successful, though generally this is wrong and this should be done from another process. But sending the dump to the pipe in the same process - this is too much :) This is like an attempt to debug the process from itself... – Alex F Dec 12 '12 at 15:49

0 Answers0