Почему MiniDumpWriteDump не работает?

Я создал собственное приложение отладчика. Он присоединяется к процессу и создает файл аварийного дампа. Это работает большую часть времени. У меня проблема в том, что он не будет работать, когда отлаживаемое приложение ожидает объект мьютекса (и это та самая проблема, которую я хочу отлаживать).

Кроме того, я создал простое приложение test.exe, которое просто зацикливается и вызывает Sleep(100), но мой отладчик дает сбой, когда он каждый раз вызывает MiniDumpWriteDump для этого приложения.

Что я делаю неправильно?

Код ошибки, который я возвращаю из приведенного ниже кода, — 2147942699 (0x8007012b).

void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
  CONTEXT c;

  memset( &c, 0, sizeof( c ) );

  GetThreadContext( hThread, &c );

  EXCEPTION_POINTERS ep;

  memset( &ep, 0, sizeof( ep ) );

  ep.ContextRecord   = &c;
  ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;

    MINIDUMP_EXCEPTION_INFORMATION minidump_exception;

  memset( &minidump_exception, 0, sizeof( minidump_exception ) );

    minidump_exception .ThreadId          = dwThreadId;
    minidump_exception.ExceptionPointers = &ep;
    minidump_exception.ClientPointers    = true;

  char txDumpPath[ MAX_PATH + 1 ];

  sprintf( txDumpPath, "%s.dmp", txProcess );

    HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

  if( hFile )
  {
    BOOL  fSuccess;


    SetLastError( 0L );

    int nDumpOptions =

    MiniDumpNormal
|    MiniDumpWithDataSegs                  
|    MiniDumpWithFullMemory                
|    MiniDumpWithHandleData                
|    MiniDumpFilterMemory                  
|    MiniDumpScanMemory                    
|    MiniDumpWithUnloadedModules           
|    MiniDumpWithIndirectlyReferencedMemory
|    MiniDumpFilterModulePaths             
|    MiniDumpWithProcessThreadData         
|    MiniDumpWithPrivateReadWriteMemory    
|    MiniDumpWithoutOptionalData           
    ;

    fSuccess = MiniDumpWriteDump( hProcess,
                                  dwProcessId,
                                  hFile,
                                  (MINIDUMP_TYPE) nDumpOptions,
                                  &minidump_exception,
                                  NULL,
                                  NULL );

    DWORD dwErr = GetLastError();

    if( ! fSuccess )
            printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );

        CloseHandle( hFile );
    }
}

Я также попытался повысить привилегии с помощью следующего фрагмента кода, который я позаимствовал у кого-то, у кого была похожая проблема:

BOOL SetDumpPrivileges()
{
    BOOL       fSuccess  = FALSE;
    HANDLE      TokenHandle = NULL;
    TOKEN_PRIVILEGES TokenPrivileges;

    if (!OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
        &TokenHandle))
    {
        printf("Could not get the process token");
        goto Cleanup;
    }

    TokenPrivileges.PrivilegeCount = 1;

    if (!LookupPrivilegeValue(NULL,
        SE_DEBUG_NAME,
        &TokenPrivileges.Privileges[0].Luid))
    {
        printf("Couldn't lookup SeDebugPrivilege name");
        goto Cleanup;
    }

    TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    //Add privileges here.
    if (!AdjustTokenPrivileges(TokenHandle,
        FALSE,
        &TokenPrivileges,
        sizeof(TokenPrivileges),
        NULL,
        NULL))
    {
        printf("Could not revoke the debug privilege");
        goto Cleanup;
    }

    fSuccess = TRUE;

Cleanup:

    if (TokenHandle)
    {
        CloseHandle(TokenHandle);
    }

    return fSuccess;
}

person SparkyNZ    schedule 23.03.2012    source источник


Ответы (2)


Я разместил вопрос в MSDN, и кто-то любезно предоставил мне ответ на мою проблему. Вот ссылка к обсуждению, и фрагмент рабочего кода, который я скопировал ниже.

void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
  CONTEXT c;

  memset( &c, 0, sizeof( c ) );

  HANDLE hThread;
  c.ContextFlags = CONTEXT_FULL;
  hThread = _OpenThread( THREAD_ALL_ACCESS, FALSE, dwThreadId );

  GetThreadContext( hThread, &c );

  EXCEPTION_POINTERS ep;

  memset( &ep, 0, sizeof( ep ) );

  ep.ContextRecord   = &c;
  ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;

  MINIDUMP_EXCEPTION_INFORMATION minidump_exception;

  memset( &minidump_exception, 0, sizeof( minidump_exception ) );

  minidump_exception.ThreadId          = dwThreadId;
  minidump_exception.ExceptionPointers = &ep;
  minidump_exception.ExceptionPointers->ContextRecord = &c;
  minidump_exception.ClientPointers    = false;

  char txDumpPath[ MAX_PATH + 1 ];

  time_t tNow = time( NULL );
  struct tm *pTm = localtime( &tNow );

  sprintf( txDumpPath, "%s.%02d%02d%04d_%02d%02d%02d.dmp", 
           txProcess,
           pTm->tm_mday,
           pTm->tm_mon,
           pTm->tm_year,
           pTm->tm_hour, 
           pTm->tm_min, 
           pTm->tm_sec );

    HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

  if( hFile != INVALID_HANDLE_VALUE ) 
  {
    BOOL  fSuccess;

    printf( "hProcess   : %d (0x%x)\n", hProcess, hProcess );
    printf( "dwProcessId: %u (0x%lx)\n", dwProcessId, dwProcessId );
    printf( "dwThreadId : %u (0x%lx)\n", dwThreadId,  dwThreadId );

    SetLastError( 0L );

    fSuccess = MiniDumpWriteDump( hProcess, 
                                  dwProcessId, 
                                  hFile, 
                                  MiniDumpNormal,
                                  &minidump_exception, 
                                  NULL, 
                                  NULL );

    DWORD dwErr = GetLastError();

    if( ! fSuccess )
    {
      printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );

      LPVOID lpMsgBuf;

      FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                     NULL,
                     dwErr,
                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                     (LPTSTR) &lpMsgBuf,
                     0,
                     NULL );

      // Display the string.
      printf( "%s\n", (LPCTSTR)lpMsgBuf );

      // Free the buffer.
      LocalFree( lpMsgBuf );
    }
  } 

  if( hThread )
    CloseHandle( hThread );
}
person SparkyNZ    schedule 25.03.2012
comment
Привет, вышеперечисленное не работает для меня. Дело в том, что у меня есть свой MiniDump, написанный из отдельного процесса. Является ли ваш обработчик сбоев вне процесса? или в процессе? Можешь просто уточнить? - person Anantha Subramaniam; 11.06.2013
comment
@AnanthaSubramaniam Извините, я опубликовал это 6 лет назад. Я честно не могу вспомнить. Я бы подумал, что поместил бы это в отдельный поток «сторожевого таймера», чтобы отслеживать мой основной поток приложения, который, должно быть, был глобальным. - person SparkyNZ; 28.03.2018

Является ли эта проблема такой же, как и другая? a-crash-dump">вопрос Я ответил этим текстом?

Не включает ли он информацию о мьютексе даже с флагом MiniDumpWithHandleData, а также, возможно, он дает сбой, потому что некоторые из флагов могут быть несовместимы с версией DebugHlp.dll, против которой вы звоните, см.: здесь

person EdChum    schedule 24.03.2012
comment
И снова здравствуйте. Нет, это другая проблема. Мой предыдущий вопрос касался написания информации о дескрипторе. Проблема, которую я здесь описываю, заключается в том, что MiniDumpWriteDump вообще ничего не записывает для большинства обрабатываемых файлов. У меня есть крошечное тестовое приложение, и оно отказывается создавать дамп любого вида (создает файл размером 0 байт). Если я прикреплю приложение отладчика к одному из наших больших приложений, оно запишет дамп. - person SparkyNZ; 25.03.2012