В моем приложении я использую Unnamed Pipes
как результат MiniDumpWriteDump
функция — я не хочу на самом деле создать файл, просто записать MiniDump в буфер памяти.
Метод для чтения байтов из канала вызывается из другого потока. Когда я звоню MiniDumpWriteDump
функция, ReadFile
а также MiniDumpWriteDump
функция никогда не возвращается.
Я пытался проверить, является ли это проблемой с плохими ручками или слишком маленьким размером труб, но когда я использую простой WriteFile
функция, все кажется в порядке (даже если размер канала меньше, чем записанная строка).
Вот часть моего кода:
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;
}
Задача ещё не решена.
Других решений пока нет …