Завершение очереди застряло

недавно мы обнаружили, что одно из наших серверных приложений (то есть служба Windows) не удалось с исключением OutOfMemory. Мы попытались выяснить, что происходит, и в итоге мы обнаружили, что объекты в очереди финализации не были финализированы, поэтому для них не может быть выполнена сборка мусора. Мы пытались выяснить, какой финализатор может вызвать такое поведение с помощью Windbg, но не можем выяснить, какой именно объект вызывает это.

С помощью команды !finalizequeue мы можем узнать это:


    0:053> !finalizequeue
    PDB symbol for clr.dll not loaded
    SyncBlocks to be cleaned up: 0
    Free-Threaded Interfaces to be released: 0
    MTA Interfaces to be released: 0
    STA Interfaces to be released: 0
    ----------------------------------
    generation 0 has 28 finalizable objects (050eab4c->050eabbc)
    generation 1 has 15 finalizable objects (050eab10->050eab4c)
    generation 2 has 658 finalizable objects (050ea0c8->050eab10)
    Ready for finalization 3027 objects (050eabbc->050edb08)
    ...

3027 — невероятно большое число (через несколько минут работы это число все еще растет и никогда не падает). Я пытался выяснить, какой объект находится по адресу 050eabbc, но он всегда разного типа, поэтому я думаю, что это не причина.

Если бы я попытался распечатать собственный стек вызовов потока финализатора, я получил бы это:


    0:053> ~2k
    *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SYSTEM32\KERNELBASE.dll - 
    ChildEBP RetAddr  
    WARNING: Stack unwind information not available. Following frames may be wrong.
    032ef09c 772f10b4 ntdll!ZwWaitForSingleObject+0xc
    *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SYSTEM32\combase.dll - 
    032ef0b0 755ff0b5 KERNELBASE!WaitForSingleObject+0x12
    032ef0e4 7554b22a combase!NdrOleDllGetClassObject+0x1399
    032ef108 755ff10c combase!PropVariantCopy+0x177b
    032ef224 75511724 combase!NdrOleDllGetClassObject+0x13f0
    032ef27c 7558115d combase!DcomChannelSetHResult+0x17c7
    032ef2d8 755fd39a combase!CoRegisterSurrogateEx+0x3494
    *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SYSTEM32\RPCRT4.dll - 
    032ef2f4 76a9e4a0 combase!NdrExtStubInitialize+0x21a9
    032ef71c 755fc779 RPCRT4!NdrComplexArrayUnmarshall+0xcac
    032ef738 75510d77 combase!NdrExtStubInitialize+0x1588
    032ef748 755816d5 combase!DcomChannelSetHResult+0xe1a
    032ef7dc 75587aa5 combase!CoRegisterSurrogateEx+0x3a0c
    *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll - 
    032ef82c 748ab680 combase!StringFromIID+0x28d
    032ef92c 748ab758 clr!PreBindAssemblyEx+0x259d
    032ef964 7487960d clr!PreBindAssemblyEx+0x2675
    032ef980 748ab55a clr!GetMetaDataInternalInterfaceFromPublic+0x2162a
    032ef9dc 74878915 clr!PreBindAssemblyEx+0x2477
    032efa2c 7487887c clr!GetMetaDataInternalInterfaceFromPublic+0x20932
    032efa44 7478a5e2 clr!GetMetaDataInternalInterfaceFromPublic+0x20899
    032efa8c 74777d71 clr!GetPrivateContextsPerfCounters+0x968

Поток финализатора всегда зависает на ZwWaitForSingleObject, так что это еще один признак того, что поток финализатора завис.

Итак, мой вопрос: как я могу узнать, какой объект вызывает зависание очереди финализатора? Самое смешное, что я вообще не использую финализаторы :-(


person user2523230    schedule 26.06.2013    source источник
comment
Качество вашей трассировки стека слишком низкое. Вам нужно будет настроить отладчик для использования сервера Microsoft Symbol, чтобы эти сообщения о том, что файл символов не найден, исчезли.   -  person Hans Passant    schedule 26.06.2013
comment
Что-то использует финализаторы. Вы используете сторонние библиотеки? Если это так, я бы начал делать обзоры кода для них. Скорее всего, финализатор разбился из-за исключений, выброшенных в финализаторе.   -  person Lasse V. Karlsen    schedule 26.06.2013
comment
Я попытался переключить атрибут STAThread на атрибут MTAThread, и он снова начал работать! Не знаю почему, потому что мы вообще не используем COM.   -  person user2523230    schedule 26.06.2013


Ответы (1)


Моя «психическая отладка» предполагает, что некоторый код, который выполняется в потоке STA, создает объект COM, но этот поток STA не следует правилам COM в отношении перекачки сообщений (и, возможно, поток вообще исчез). Я говорю это только потому, что мы видим combase в стеке вызовов финализатора. Очевидно, вам нужны правильные символы и просмотрите как собственный, так и управляемый стеки вызовов:

.symfix C:\localsymbolcache .reload ~2s kb !clrstack

Опубликуйте результаты, если вы хотите воскресить этот вопрос.

person Sasha Goldshtein    schedule 25.08.2014
comment
Аналогичные случаи здесь с дополнительной информацией о стеке: stackoverflow. ком/вопросы/41010449/ - person Igor Malin; 08.12.2016