Помогите поймать StackruException с WinDbg и ADPlus
Укороченная версия
Я хочу сценарий ADPlus, который будет делать полный дамп памяти для исключительной ситуации StackruException, прежде чем что-либо очистить, и игнорировать все другие типы исключений.
Версия журнала
После выпуска нового кода ASP.NET мы начали периодически получать StackruExceptions. Мы искали бесконечные рекурсии и всех обычных подозреваемых в ревизиях, добавленных со времени последней удачной установки, и не можем ничего найти. Веб-сайт будет работать в течение часа, а затем рухнет.
Мы использовали WinDbg и SOS и попытались получить журналы сбоев с помощью ADPlus, используя эту команду:
adplus -crash -o D:\Crash -NoDumpOnFirst -iis
Причина -NoDumpOnFirst в том, что мы можем воспроизвести эту ошибку только в рабочей среде на занятых серверах. Чтобы выполнить мини-дамп для каждого исключения первого шанса (эй, это происходит), отладчик должен приостановить рабочий процесс IIS достаточно долго, чтобы записать файл размером 16 мегабайт, поэтому запросы встают в очередь, и приложение становится нестабильным. Поскольку ошибка может занять до часа, чтобы поднять ее уродливую голову, это проблематично.
Итак, с -NoDumpOnFirst я получаю файл дампа, который WinDbg выводит для следующих потоков:
PDB symbol for mscorwks.dll not loaded
ThreadCount: 69
UnstartedThread: 0
BackgroundThread: 69
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
XXXX 1 c6c 000fa758 11808221 Disabled 3b49ee4c:3b49efe8 00120888 1 Ukn (Threadpool Worker)
XXXX 2 1294 000fd258 b220 Enabled 00000000:00000000 000df4e0 0 Ukn (Finalizer)
XXXX 3 1eb0 0011cdd0 80a220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Completion Port)
XXXX 4 1b3c 00120198 1220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 5 1280 00138118 880a220 Enabled 2633de9c:2633ee08 000df4e0 0 Ukn (Threadpool Completion Port)
XXXX 6 1db8 00158a48 1180a221 Disabled 4b5a7e2c:4b5a82e8 00120888 1 Ukn (Threadpool Worker)
XXXX 9 141c 00162008 180a220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 7 1574 00174008 180a220 Enabled 4d46b6a8:4d46c158 00120888 2 Ukn (Threadpool Worker)
XXXX c 16c8 0016b7a8 180a220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 8 1384 00162878 180a220 Enabled 284e26a4:284e45d8 000df4e0 0 Ukn (Threadpool Worker)
XXXX b 1c10 0016b3d8 180a220 Enabled 3ed2dae0:3ed2dfe8 00120888 2 Ukn (Threadpool Worker)
XXXX a 1814 0016b008 180a220 Disabled 28816384:28816638 00120888 1 Ukn (Threadpool Worker)
XXXX d 1fc 1b4d1ff0 220 Enabled 319f89a4:319fa41c 000df4e0 0 Ukn
XXXX e 1864 1b4e3d20 180b220 Enabled 4b2c5be0:4b2c6150 000df4e0 0 Ukn (Threadpool Worker)
XXXX f 13bc 1b57caf8 200b220 Enabled 4cc71584:4cc73414 00120888 1 Ukn
XXXX 10 72c 1f5124a8 180b220 Enabled 3b4b3414:3b4b4fe8 00120888 2 Ukn (Threadpool Worker)
XXXX 11 1fd0 1f526398 180b220 Disabled 4d46f41c:4d470158 00120888 1 Ukn (Threadpool Worker)
XXXX 12 1f10 1f52f1c8 180b220 Enabled 28812c14:28814638 00120888 2 Ukn (Threadpool Worker)
XXXX 13 1b84 1f53a420 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 14 18a4 1f570978 180b220 Enabled 263e18b4:263e2e28 000df4e0 0 Ukn (Threadpool Worker)
XXXX 15 1a98 1f57f0a0 180b220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 16 1b4 1f583628 180b220 Enabled 495781ec:4957914c 00120888 2 Ukn (Threadpool Worker)
XXXX 17 b90 1f585dc8 180b220 Enabled 265cbe48:265ccba4 000df4e0 0 Ukn (Threadpool Worker)
XXXX 18 1590 1f613c60 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 19 1850 1f5fad90 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 1a c78 1f60d3f0 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 1c 1bd8 2121f1b0 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 1d 494 1b4a8c10 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 1e 898 2120f120 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 1f 1820 21355ff8 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 20 15b0 3570e120 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 21 18b0 359ca008 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 22 75c 35a58948 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 25 1a18 213ac8f8 880b220 Disabled 3219a830:3219b450 00120888 1 Ukn (Threadpool Completion Port) System.StackruException (0e3200a4)
XXXX 29 1b74 3598e620 180b220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 2a 9b8 3598dbe0 180b220 Enabled 2880ef2c:28810638 000df4e0 0 Ukn (Threadpool Worker)
XXXX 2b 1eac 1f6f6288 180b220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 2d 2f4 211759e8 180b220 Disabled 2634eacc:2634ee08 00120888 1 Ukn (Threadpool Worker)
XXXX 2e 1e3c 35c2eb60 880b220 Enabled 4b5a5758:4b5a62e8 000df4e0 0 Ukn (Threadpool Completion Port)
XXXX 30 394 35c394f8 180b220 Enabled 4cef7930:4cef90d4 000df4e0 0 Ukn (Threadpool Worker)
XXXX 31 1e64 35c39128 180b220 Disabled 288110b0:28812638 00120888 1 Ukn (Threadpool Worker)
XXXX 32 1af8 35a58578 180b220 Enabled 3b48e7cc:3b48efe8 000df4e0 0 Ukn (Threadpool Worker)
XXXX 34 1d44 1f6a6c88 180b220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 35 197c 212088e0 180b220 Enabled 49389ba8:4938af40 000df4e0 0 Ukn (Threadpool Worker)
XXXX 36 1e2c 35c1d980 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 38 1ddc 212d03d8 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 39 288 212d0008 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 3a 1694 212bf958 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 3b be4 212ccc40 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 37 ccc 35c4d6d0 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 3c 14ec 35c55af0 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 41 1d94 35c38c08 180b220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 24 130 35746a50 180b220 Enabled 2670ae48:2670cc00 000df4e0 0 Ukn (Threadpool Worker)
XXXX 2f 1404 35c1d350 180b220 Enabled 00000000:00000000 000df4e0 0 Ukn (Threadpool Worker)
XXXX 43 1ae8 35c25cb8 180b220 Disabled 3b4c28e0:3b4c2fe8 00120888 1 Ukn (Threadpool Worker)
XXXX 44 18ac 212cc870 180b220 Disabled 4957e728:4957f14c 00120888 1 Ukn (Threadpool Worker)
XXXX 45 18b4 212bf588 180b220 Disabled 3b4c05dc:3b4c0fe8 00120888 1 Ukn (Threadpool Worker)
XXXX 46 1c0c 21239858 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 47 4fc 21188b68 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 48 1198 35caa2a8 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 49 1f9c 21147af8 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 4a 1adc 35cc6908 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 4b ce8 35c60e30 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 4d 6f0 35d05aa0 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 4e 1ee8 35c1b6b0 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 42 1d7c 35d9a230 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 3d 7d8 212e1b28 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 23 c0c 503ea010 220 Enabled 00000000:00000000 000df4e0 0 Ukn
XXXX 27 1f44 503cdf08 220 Enabled 00000000:00000000 000df4e0 0 Ukn
Попытка распечатать исключение показывает, что нет трассировки стека, а другие методы жалуются, что это неуправляемый код. Я предполагаю, что поскольку дамп создается при смерти процесса, все потоки были собраны сборщиком мусора, и информации больше не осталось.
Мне бы очень хотелось, чтобы отладчик выполнил полный дамп первого шанса StackruException и игнорировал все другие типы исключений. Я знаю, что ADPlus может использовать конфигурационный файл - http://msdn.microsoft.com/en-us/library/cc409304.aspx - но формат мне подходит. Может кто-нибудь показать мне, как сделать сценарий ADPlus, который будет делать это?
... конечно, если вы посмотрите на список веток выше и точно знаете, что не так, или могли бы выяснить, если бы я дал вам больше информации, вы можете просто сказать мне об этом.
Попытка разрешения 1
Спасибо Димок за ответ ниже, он был не совсем правильным, но это подтолкнуло меня в правильном направлении. Код исключения для переполнения стека был неправильным (это sbo, а не sov) (или, как я думал в то время, см. Правки deemok ниже), поэтому я попытался отладить следующую конфигурацию:
<ADPlus>
<!-- Add log entry, log faulting thread stack and dump full on first chance Stackru -->
<Exceptions>
<Config>
<!-- This is for the Stackru exception -->
<Code> sbo </Code>
<Actions1> Log;Stack;FullDump </Actions1>
<!-- Depending on what you intend - either stop the debugger (Q or QQ) or continue unhandled (GN) -->
<ReturnAction1> GN </ReturnAction1>
</Config>
</Exceptions>
</ADPlus>
И с помощью следующей команды:
adplus -crash -o D:\Crash -NoDumpOnFirst -c D:\Crash\stackru.cfg -iis
Я проверил, что выходные файлы журнала указали правильную конфигурацию. Хитрость в том, что параметры командной строки adplus выполняются по порядку, поэтому, если вы начнете с конфигурации, которая перехватывает исключения первого шанса, а затем примете -NoDumpOnFirst, параметры конфигурации будут перезаписаны. Если вы примените конфиг с параметром -c last, то его настройки победят.
В конце концов, однако, переполнение стека оказалось неуловимым. Произошло переполнение стека, не удалось получить дамп памяти, а затем произошел дамп для события завершения второго варианта, и снова все было собрано мусором, и я не смог получить никакой полезной информации.
Я попытался замкнуть исключение завершения процесса, в случае, если это включало и перекрывало переполнение стека, но затем возникло исключение, и я просто не получил дамп памяти.
К счастью, я наткнулся на ответ, изучив код. Конечно, это был случай кругового вызова метода.
Фактическое разрешение
Проблема была решена давно, но я быстро создал страницу ASP.NET, которая могла вызвать переполнение стека. (Это не сложно сделать в конце концов) и попробовал ответ Axl ниже.
XML был немного не в порядке - Axl просто забыл закрыть </ADPlus>
тег (или probaby потерял его в копировальной пасте), но это было достаточно легко исправить, и adplus был достаточно любезен, чтобы сказать мне, что именно не так.
Я отключил этот сценарий от своего метателя переполнения тестового стека, загрузил результат в windbg, и когда я вызвал! Clrstack, я получил очень четкий (и длинный) список методов, которые вызывали друг друга по кругу. Это нашло бы проблему в одно мгновение! Я буду держать эту страницу в закладке в следующий раз, когда переполнение стека будет стучать в мою дверь.
2 ответа
На всякий случай это может помочь кому-то еще, ниже приведен файл конфигурации ADPlus, который я придумал. Глядя на это сейчас, я не уверен, что побег имеет какой-либо эффект. Присоединяется, когда приложение ASP.NET, которое выдает исключение StackruException, генерирует файлы ".dmp с 1-м шансом заполнения Stackru" и ". С 1-м шансом завершения процесса".dmp в указанном OutputDir. Откройте первый файл с помощью Windbg и запустите ".loadby sos mscorwks", а затем "! Clrstack", чтобы увидеть, что может быть причиной переполнения стека.
<ADPlus>
<Settings>
<RunMode>CRASH</RunMode>
<OutputDir>C:\Dumps</OutputDir>
<ProcessName>w3wp.exe</ProcessName>
</Settings>
<Exceptions>
<Option>FullDumpOnFirstChance</Option>
<Option>MiniDumpOnSecondChance</Option>
<Option>NoDumpOnFirstChance</Option>
<Option>NoDumpOnSecondChance</Option>
<Config>
<Code>AllExceptions</Code>
<Actions1>Void</Actions1>
<Actions2>Void</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Config>
<Config>
<!--
av = AccessViolation
ch = InvalidHandle
ii = IllegalInstruction
dz = IntegerDivide
c000008e = FloatingDivide
iov = IntegerOverflow
lsq = InvalidLockSequence
sov = StackruException
eh = CPlusPlusEH
* = UnknownException
clr = NET_CLR
bpe = CONTRL_C_OR_Debug_Break
ld = DLL_Load
ud = DLL_UnLoad
epr = Process_Shut_Down
sbo = Stack_buffer_overflow
-->
<Code>sov;sbo</Code>
<Actions1>Log;Time;Stack;FullDump;EventLog</Actions1>
<CustomActions1>!runaway</CustomActions1>
<Actions2>Log;Time;Stack;FullDump;EventLog</Actions2>
<CustomActions2>!runaway</CustomActions2>
<!--
G = go
GN = go unhandled exception
GH = go handled exception
Q = quit
QD = quit and detach
-->
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Config>
<Config>
<Code>clr</Code>
<Actions1>Void</Actions1>
<Actions2>Log;Time;Stack;FullDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Config>
<Config>
<Code>epr</Code>
<Actions1>Log;Time;Stack;FullDump;EventLog</Actions1>
<Actions2>Void</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Config>
</Exceptions>
</ADPlus>
<Исключения> sbo Code>
Log;Stack;FullDump Actions1> GN ReturnAction1> Исключения> ADPlus>
Сохраните это в stackru.cfg
Тогда вы можете пойти:
adplus -c stackru.cfg
Редактировать: и sov, и sbo являются исключениями переполнения стека. Я думаю, что нужно экспериментировать с обоими, так как мне не совсем понятно, в чем разница между ними. (может ли sbo обозначить неверный вызов alloca()?)