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

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


Мы используем _1 _ для записи аварийного дампа, когда в нашем приложении есть необработанное исключение / 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 в любом случае должен приостановить потоки процесса, поэтому, если бы мы сначала написали большой дамп, у нас был бы большой дамп точнее маленького.

Вопрос

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


person Martin Ba    schedule 29.04.2013    source источник


Ответы (3)


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

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

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

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

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

person xwlan    schedule 07.05.2013

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

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

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

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

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

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

person Steve    schedule 29.04.2013
comment
Обратите внимание, что мы пишем их впоследствии, а не одновременно. Но, тем не менее, информация приветствуется, иначе кому-то придет в голову попытаться написать их одновременно. - person Martin Ba; 29.04.2013
comment
Таким образом вы с большей вероятностью получите некоторые данные быстро, а не будете ждать полного дампа. - Что именно вы здесь имеете в виду? См. Мой вопрос: ... необходимо приостановить ... в любом случае, поэтому, если бы мы сначала написали большой дамп, у нас было бы ... более точно ... - person Martin Ba; 29.04.2013
comment
@MartinBa Я обновил ответ, включив в него свои причины. Это действительно по причинам человеческого фактора, чем по техническим причинам. - person Steve; 29.04.2013

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

person Marc Sherman    schedule 29.04.2013
comment
Поскольку я вызываю MDWD из процесса, я, вероятно, мог бы просто приостановить их все. Интересно, должно ли это - сначала приостановить потоки, а затем вызвать MDWD - работать. Вы когда-нибудь пробовали это? - person Martin Ba; 29.04.2013
comment
Я никогда не пробовал, но вы можете легко попробовать, используя windbg, чтобы приостановить все потоки ~*n, а затем отсоединиться от процесса с помощью .detach. Теперь у целевого процесса будут приостановлены все потоки. Теперь вызовите MDWD из другого процесса и посмотрите, согласованы ли оба дампа. Когда вы будете готовы возобновить все потоки в целевом процессе, просто повторно подключитесь к целевому процессу с помощью windbg и используйте ~*m, чтобы возобновить их, а затем .detach. Ваш целевой процесс снова будет нормально работать. - person Marc Sherman; 29.04.2013