Подтвердить что ты не робот

Помогите поймать StackOverflowException с помощью WinDbg и ADPlus

Краткая версия

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

Версия журнала

После выпуска нового кода ASP.NET мы начали получать прерывистые StackOverflowExceptions. Мы искали бесконечные рекурсии и все обычные подозреваемые в версиях, добавленных после последней известной хорошей установки, и ничего не можем найти. Веб-сайт будет работать до часа, а затем сбой.

Мы использовали WinDbg и SOS и пытались получить журналы сбоев с помощью ADPlus, используя следующую команду:

adplus -crash -o D:\Crash -NoDumpOnFirst -iis

Причина -NoDumpOnFirst заключается в том, что мы можем только воспроизвести эту ошибку при производстве на занятых серверах. Чтобы выполнить minidump при каждом исключении из первого шанса (эй, это так), отладчик должен приостановить рабочий процесс 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.StackOverflowException (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

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

Мне бы очень хотелось, чтобы отладчик выполнял полный дамп по первому шансу StackOverflowException и игнорировал все другие типы исключений. Я знаю, что ADPlus может использовать конфигурационный файл - http://msdn.microsoft.com/en-us/library/cc409304.aspx - но формат для меня все греческий. Может ли кто-нибудь показать мне, как сделать ADPlus script, который это сделает?

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

Решение Попытка 1

Спасибо Deemok за ответ ниже, это было не совсем правильно, но это подтолкнуло меня в правильном направлении. Код исключения для был неправильным (это sbo not sov), (или так я думал в то время, см. Ниже), поэтому я попробовал отладку со следующей конфигурацией:

<ADPlus>
   <!-- Add log entry, log faulting thread stack and dump full on first chance StackOverflow -->
<Exceptions>
     <Config>
        <!-- This is for the StackOverflow 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\stackoverflow.cfg -iis

Я проверил, что выведенные файлы журналов указали правильную конфигурацию. Хитрость заключается в том, что параметры командной строки adplus выполняются по порядку, поэтому, если вы начинаете с конфига, который перехватывает случайные исключения и затем применяет -NoDumpOnFirst, параметры конфигурации будут перезаписаны. Если вы примените конфигурацию с -c последним, тогда ее настройки выиграют.

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

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

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

Фактическое разрешение

Проблема была решена давно, но я быстро создал страницу ASP.NET, которая вызовет переполнение стека. (Это не сложно сделать в конце концов) и попытался ответить Axl ниже.

XML был слегка выключен - Axl просто забыл закрыть тег </ADPlus> (или probaby потерял его в copy-paste), но это было достаточно легко, и adplus был достаточно любезен, чтобы сказать мне, что именно было ошибкой.

Я установил, что script выключен против моего метадателя переполнения тестового стека, загрузил результат в windbg, и когда я позвонил! clrstack, я получил очень четкий (и длинный) список методов, которые вызывали друг друга круговыми. Это нашло бы проблему в одно мгновение! Я буду держать эту страницу закладок в следующий раз, когда переполнение стека приходит в мою дверь.

4b9b3361

Ответ 1

На всякий случай это может помочь кому-то еще, ниже представлен файл конфигурации ADPlus. Глядя на это сейчас, я не уверен, что беглец имеет какой-то эффект. При запуске приложения ASP.NET, которое генерирует StackOverflowException, оно будет генерировать "1st chance StackOverflow full" и "1st chance Process Shut Down full".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 = StackOverflowException
        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>

Ответ 2

<ADPlus>
   <!-- Add log entry, log faulting thread stack and dump full on first chance StackOverflow -->
<Exceptions>
     <Config>
        <!-- This is for the stack buffer overflow exception -->
        <!-- Use sov for Qaru 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>

Сохраните это в файле stackoverflow.cfg
Тогда вы можете пойти:

adplus -c stackoverflow.cfg

Изменить: оба sov и sbo являются исключениями. Думаю, нужно экспериментировать с обоими, так как мне не совсем понятно, какая разница между ними. (может ли sbo обозначить недопустимый вызов alloca()?)