Есть ли способ узнать идентификатор потока в другом процессе, который вызывает исключение? - PullRequest
5 голосов
/ 04 ноября 2010

Я пытаюсь использовать API MiniDumpWriteDump () для выгрузки аварийного процесса B из другого процесса A. Я делаю это, потому что MSDN сказал так:

MiniDumpWriteDump должен бытьвызывается из отдельного процесса, если это вообще возможно, а не из целевого процесса, который выводится.

MiniDumpWriteDump () определяется следующим образом:

BOOL WINAPI MiniDumpWriteDump(
  __in  HANDLE hProcess,
  __in  DWORD ProcessId,
  __in  HANDLE hFile,
  __in  MINIDUMP_TYPE DumpType,
  __in  PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  __in  PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  __in  PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);

В частности,ExceptionParam имеет тип PMINIDUMP_EXCEPTION_INFORMATION , который определяется следующим образом:

typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
  DWORD               ThreadId;
  PEXCEPTION_POINTERS ExceptionPointers;
  BOOL                ClientPointers;
} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;

Теперь мне интересно, как подготовить следующие 2 параметра:

ThreadId Идентификатор потока, выдавшего исключение.

ExceptionPointers Указатель на структуру EXCEPTION_POINTERS, указывающую независимое от компьютера описание исключения и контекст процессора во время исключения.

Как получить идентификатор ошибочного потока и указатели исключений в процессе B при запуске в процессе A?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 13 ноября 2010

Указатель на структуру MINIDUMP_EXCEPTION_INFORMATION, описывающую исключение клиента, которое вызвало создание минидампа. Если значение этого параметра равно NULL, информация об исключении не включается в файл мини-дамп.

Несмотря на то, что параметр помечен __in, а не __in_opt, вы действительно можете передать значение NULL здесь. Чтобы получить эту информацию в первую очередь от целевого процесса, ваш процесс все равно должен был бы отлаживать ее.

Как и когда известно, что процесс A получает мини-дамп процесса B? Если A действительно отлаживает B, когда WaitForDebugEvent возвращается с EXCEPTION_DEBUG_EVENT, информация доступна в информационной структуре.

Если A не отлаживает B, то, возможно, B сообщает A через какой-то механизм IPC: «Эй, я рушусь, сделайте мини-дамп». В этом случае либо B может принять сам дамп, либо передать информацию об исключении через тот же механизм IPC в A. Опять же, это проблематично по тем же причинам, что вызвать MiniDumpWriteDump в процессе сбоя проблематично, если что-то взрывается, вещь то, что могло взорваться, может быть тем, что вам нужно, чтобы рассказать об этом А.

Другой механизм, который может заставить A принять дамп для B, - это A, установленный как отладчик JIT, в этом случае A будет отлаживать B, и вы можете использовать API отладки для получения информации об исключении.

Если A просто периодически принимает мини-дамп B, исключений не обязательно будет, поэтому в этом случае вы можете просто пропустить NULL.

Обратите внимание, что если вы собираетесь сделать что-то вроде

WaitForSingleObject(handleToProcessB, INFINITE);
MiniDumpWriteDump(handleToProcessB, ...)

что это не будет работать. ОС хранит очень мало вещей, в основном код завершения процесса, а не виртуальное адресное пространство и стеки, которые вам нужны для мини-дамп.

0 голосов
/ 08 ноября 2010

Чтобы создать автоматический дамп для данного исключения для определенного имени процесса, я бы посоветовал использовать DebugDiag или AdPlus. Это внешнее (и бесплатное!) Программное обеспечение, которое вы можете настроить для этого.

Если вы действительно хотите написать дамп самостоятельно, вы можете сделать это в процессе B: MSDN предупреждает вас, что это не очень хорошая идея, потому что неприятные ошибки, такие как нехватка памяти, переполнение стека или повреждение стека (список не исчерпывающий), безусловно, будет использовать память и стек, так что вы можете закончить без дампа вообще (и очень плохой сбой процесса). По моему опыту, это довольно редко (я работал над очень напряженным распределенным программным обеспечением C ++). Для других, это должно быть хорошо. В этом случае вы можете использовать транслятор исключений (см. _Set_se_translator) или векторный обработчик исключений (см. AddVectoredContinueHandler) или функцию GetExceptionInformation () для получения структуры EXCEPTION_RECORD (могут быть и другие способы, о которых я не знаю).

Создание дампа из процесса A после исключения в процессе B означает, что вы должны скопировать всю информацию об исключении и предупредить процесс A о том, что он должен что-то сделать с этим исключением. Это будет занимать память и стек, поэтому у вас будет такое же ограничение, как описано выше.

Надеюсь, что поможет

...