MiniDumpWriteDump и запись нескольких дампов для одного и того же сбоя?

TL;DR Имеет ли смысл писать несколько дампов для одного и того же события сбоя, и если да, то на что вам нужно обращать внимание.


Мы используем MiniDumpWriteDump написать аварийный дамп, когда в нашем приложении есть необработанное исключение / abort / younameit.

Код до сих пор фактически записывает два дампа:

  • Один с MiniDumpWithDataSegs чтобы получить маленький, который может быть отправлен даже дерьмовой электронной почтой без проблемы однажды заархивированный.
  • Полный MiniDumpWithFullMemory иметь полную доступную информацию, если она нам понадобится.

Чтобы сделать эту работу, мы звоним MiniDUmpWriteDump дважды:

1 Open/create file for small dump
2 Write small dump
3 Open/create file for large dump
4 Write large dump

Насколько я могу судить, одна дополнительная идея этой схемы заключалась в том, что написание небольшого дампа происходит быстрее. В основном это всегда меньше секунды, хотя написание большого дампа часто может занимать несколько секунд, особенно когда приложение полностью загружено и большой дамп легко составит 1,2 ГБ или более.

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

Очевидно, что потоки процесса продолжают выполняться между окончанием первого вызова и началом второго вызова MDWP, поэтому у нас есть довольно много случаев, когда информация в маленьком дампе на самом деле более точна, чем информация в большая свалка

Подумав об этом, я бы предположил, однако, что написать дамп, MiniDumpWriteDump В любом случае необходимо приостановить потоки процесса, поэтому, если бы мы сначала записали большой дамп, большой дамп был бы более точным, чем маленький.

Вопрос

Должны ли мы написать большой дамп перед малым? Должны ли мы даже писать два дампа? Можем ли мы каким-то образом заставить систему сначала приостановить потоки процесса, а затем записать два дампа, которые являются полностью "синхронными"?

3 ответа

Решение

Я когда-либо анализировал дампы от разных клиентов в течение пары лет, ниже приведены только мои личные взгляды на ваш вопрос, надеюсь, это поможет.

Должны ли мы написать большой дамп перед малым? Я не считаю, что порядок важен для аварий, зависаний и других типичных проблем. есть место крушения, тупик там, на свалке, сначала захваченный или после.

Должны ли мы даже писать два дампа? я бы предложил написать хотя бы 1 полный дамп, небольшой дамп очень удобен для вас, чтобы получить первоначальное представление о том, в чем проблема, но это очень ограниченный esp. когда ваше приложение падает. поэтому вы можете предложить клиенту отправить вам небольшой дамп по электронной почте для выполнения первого раунда сортировки, если это не поможет вам найти основную причину, а затем запросить полный дамп. технически вы можете удалить небольшой дамп из полного дампа, однако вы можете не захотеть, чтобы ваш клиент выполнял такую ​​работу за вас. так что это зависит от того, как вы взаимодействуете со своим клиентом.

Можем ли мы каким-то образом заставить систему сначала приостановить потоки процесса, а затем записать два дампа, которые являются полностью "синхронными"?

технически это выполнимо. например, это относительно легко сделать out-proc, простой NtSuspendProcess() приостанавливает все целевые потоки, но он должен вызываться из другого процесса. если вы предпочитаете делать внутрипроцессное, вы должны перечислить все потоки и вызвать SuspendThread(), так работает MiniDumpWriteDump(). Тем не менее, я думаю, что синхронизация / асинхронность не влияет на точность дампа.

Запись двух дампов одновременно не рекомендуется, потому что MiniDumpWriteDump не является потокобезопасным.

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

Нужно ли вам писать большой дамп с небольшим дампом, зависит от вашего приложения и ожидаемых ошибок. Мини-дамп содержит только информацию о стеке, он не содержит кучи памяти, информацию о дескрипторах или недавно выгруженные модули.

Получение информации о стеке, очевидно, даст вам трассировку стека, но если трассировка стека говорит вам только о том, что вашим последним действием было обращение к некоторой памяти в куче, трассировка не очень полезна. Ваши ожидаемые режимы отказа будут диктовать, что имеет больше смысла. Если у вас есть устаревший код, который, возможно, не использует RAII для управления дескрипторами, или обработка выделенной памяти для кучи не так управляема, как вам бы хотелось, тогда будет полезен полный дамп.

Вы должны также рассмотреть человека, который представит дамп памяти. Если ваши клиенты находятся в Интернете, им может не понравиться отправлять значительный дамп памяти. Они могут также беспокоиться о личных данных, которые также могут быть отправлены вместе с полным дампом памяти. Minimdump намного меньше и его легче отправить, и он менее вероятен (хотя и не невозможен) для хранения личных данных. Если ваши клиенты работают во внутренней сети, тогда полный дамп памяти более приемлем.

Лучше сначала написать мини-дамп, а затем большой дамп. Таким образом, вы с большей вероятностью получите некоторые данные быстрее, чем ожидаете полного дампа. Полный дамп может занять некоторое время, а пользователи часто нетерпеливы. Они могут решить убить процесс, чтобы вернуться к работе. Кроме того, если диск заполняется (возможно, причиной сбоя), скорее всего, у вас есть место для мини-дампа, чем для полного дампа.

DbgHelp.dll импортирует SuspendThread и ResumeThread. Вы можете сделать то же самое. Вызовите SuspendThread для всех потоков (за исключением, конечно, текущего), вызовите MiniDumpWriteDump столько раз, сколько вам нужно, затем вызовите ResumeThread для каждого приостановленного потока. Это должно дать вам постоянно точные свалки.

Другие вопросы по тегам