clr!_EH_epilog3是什么意思?

时间:2017-07-13 17:30:23

标签: debugging garbage-collection clr

我在申请方面遇到了僵局。 我对转储的研究给出了以下结果: 1)有几个主题:

0:022> !threads
ThreadCount:      23
UnstartedThread:  1
BackgroundThread: 21
PendingThread:    1
DeadThread:       0
Hosted Runtime:   no
                                                                         Lock  
       ID OSID ThreadOBJ    State GC Mode     GC Alloc Context  Domain   Count Apt Exception
   0    1  bc8 01108a10     26020 Preemptive  00000000:00000000 01102c30 0     STA 
   2    2 1380 011169c0     2b220 Preemptive  00000000:00000000 01102c30 0     MTA (Finalizer) 
   4    3  a1c 011c9c28   102a220 Preemptive  00000000:00000000 01102c30 0     MTA (Threadpool Worker) 
   5    4 13dc 011a1118   1020220 Preemptive  00000000:00000000 01102c30 0     Ukn (Threadpool Worker) 
   7    7 11dc 0793ff00     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
   8    8  e08 0798a910     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
   9    9 1314 07a11800     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  10   10  c40 07a2ee40     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  11   11  dfc 07a1cf68     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  12   12  ed8 07a8bcb0     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  19   13 1328 07a8c1f8     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  14   14 1114 07a9c970     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  15   15 10ac 07a8d0f8     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  16   16  ad8 07a8d918     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  17   17  640 07a72d98     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  18   18  620 07a72308     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  13   19 1198 07a70de8     20220 Preemptive  00000000:00000000 01102c30 0     Ukn 
  20   20  594 07a6f380   1029220 Preemptive  00000000:00000000 01102c30 0     MTA (Threadpool Worker) 
  21   21 116c 07a6f8c8   1039220 Preemptive  00000000:00000000 01102c30 0     Ukn (Threadpool Worker) 
  22   24  fb4 0c7c2340   1029220 Cooperative 00000000:00000000 01102c30 2     MTA (GC) (Threadpool Worker) 
  23    5  b10 0a9c6608   8039220 Preemptive  00000000:00000000 01102c30 0     Ukn (Threadpool Completion Port) 
  24    6  164 0c7c6298   8029220 Preemptive  00000000:00000000 01102c30 0     MTA (Threadpool Completion Port) 
  26   23  e9c 07a71330      1600 Preemptive  00000000:00000000 01102c30 0     Ukn 

2)线程0,9,12,13,14,15,16,17,18,19,20,21和23等待GC完成。因为他们有类似的callstack。像这样:

00 048fec90 76c12cc7 000001bc 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 048fed04 74d74b85 000001bc ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x99 (FPO: [SEH])
02 048fed34 74d74bcc 00000000 3629c685 00000000 clr!CLREventWaitHelper2+0x31 (FPO: [Non-Fpo])
03 048fed84 74d74b4f 00000000 3629c6bd 0a9c6608 clr!CLREventWaitHelper+0x2a (FPO: [Non-Fpo])
04 048fedbc 74e52c82 ffffffff 00000000 00000000 clr!CLREventBase::WaitEx+0x152 (FPO: [Non-Fpo])
05 048fedd0 74e55e8d 00000000 3629c6e1 0a9c6608 clr!WKS::GCHeap::WaitUntilGCComplete+0x34 (FPO: [1,0,0])
06 048fee20 74d698cc 00000005 048fee64 ffffffff clr!Thread::RareDisablePreemptiveGC+0x1dc (FPO: [0,13,0])
...

3)线程22的调用堆栈看起来像是在等待某事:

00 0a26e730 76c12cc7 000001c8 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 0a26e7a4 74d74b85 000001c8 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x99 (FPO: [SEH])
02 0a26e7d4 74d74bcc 00000000 3880c325 00000000 clr!CLREventWaitHelper2+0x31 (FPO: [Non-Fpo])
03 0a26e824 74d74b4f 00000000 3880c35d 07a71330 clr!CLREventWaitHelper+0x2a (FPO: [Non-Fpo])
04 0a26e85c 74ef33a9 ffffffff 00000000 00000000 clr!CLREventBase::WaitEx+0x152 (FPO: [Non-Fpo])
05 0a26e878 74ef33da 3880c3b9 753b11d0 00000000 clr!WKS::gc_heap::create_bgc_thread+0x4e (FPO: [0,0,0])
06 0a26e8b8 74e4f783 00000010 00000000 00000003 clr!WKS::gc_heap::garbage_collect+0x38a (FPO: [Non-Fpo])
07 0a26e8e0 74e52be0 00000000 00000000 0c7c2380 clr!WKS::GCHeap::GarbageCollectGeneration+0x203 (FPO: [2,5,4])
08 0a26e904 74e4f0db 00000000 0b48bb5c 0c7c2380 clr!WKS::gc_heap::try_allocate_more_space+0x157 (FPO: [Non-Fpo])
09 0a26e91c 74e4f24f 00000000 00000010 010fd130 clr!WKS::gc_heap::allocate_more_space+0x18 (FPO: [1,0,0])
0a 0a26e934 74d692e6 00000010 00000010 00000002 clr!WKS::GCHeap::Alloc+0x4f (FPO: [Non-Fpo])
...

此线程的Dumpstack看起来像这样:

ChildEBP RetAddr  Caller, Callee
0a26e730 76c12cc7 KERNELBASE!WaitForSingleObjectEx+0x99, calling ntdll!NtWaitForSingleObject
0a26e7a4 74d74b85 clr!CLREventWaitHelper2+0x31
0a26e7d4 74d74bcc clr!CLREventWaitHelper+0x2a, calling clr!CLREventWaitHelper2
0a26e824 74d74b4f clr!CLREventBase::WaitEx+0x152, calling clr!CLREventWaitHelper
0a26e83c 74df70ea clr!Thread::StartThread+0x71, calling clr!_EH_epilog3
0a26e85c 74ef33a9 clr!WKS::gc_heap::create_bgc_thread+0x4e, calling clr!CLREventBase::WaitEx
0a26e878 74ef33da clr!WKS::gc_heap::garbage_collect+0x38a, calling clr!WKS::gc_heap::create_bgc_thread
0a26e894 74e52b98 clr!WKS::gc_heap::wait_for_bgc_high_memory+0x111, calling clr!__security_check_cookie
0a26e8b8 74e4f783 clr!WKS::GCHeap::GarbageCollectGeneration+0x203, calling clr!WKS::gc_heap::garbage_collect
0a26e8e0 74e52be0 clr!WKS::gc_heap::try_allocate_more_space+0x157, calling clr!WKS::GCHeap::GarbageCollectGeneration
0a26e904 74e4f0db clr!WKS::gc_heap::allocate_more_space+0x18, calling clr!WKS::gc_heap::try_allocate_more_space
0a26e91c 74e4f24f clr!WKS::GCHeap::Alloc+0x4f, calling clr!WKS::gc_heap::allocate_more_space
0a26e934 74d692e6 clr!Alloc+0x54
0a26e954 74d6940f clr!AllocateObject+0x94, calling clr!Alloc
0a26e970 74d73bf6 clr!ObjIsInstanceOfNoGC+0x13d, calling clr!MethodTable::CanCastToClassNoGC
0a26e98c 74d62adc clr!HelperMethodFrame::Push+0x10, calling clr!GetThread
0a26e994 74d694a3 clr!JIT_New+0x6b, calling clr!AllocateObject
0a26e9cc 0825f15f (MethodDesc 08201884 +0x97 NHibernate.Loader.Loader.InstanceNotYetLoaded(System.Data.IDataReader, Int32, NHibernate.Persister.Entity.ILoadable, NHibernate.Engine.EntityKey, NHibernate.LockMode, System.String, NHibernate.Engine.EntityKey, System.Object, System.Collections.IList, NHibernate.Engine.ISessionImplementor)), calling 0757329e
0a26e9e4 0825ec49 (MethodDesc 0820186c +0x129 NHibernate.Loader.Loader.GetRow(System.Data.IDataReader, NHibernate.Persister.Entity.ILoadable[], NHibernate.Engine.EntityKey[], System.Object, NHibernate.Engine.EntityKey, NHibernate.LockMode[], System.Collections.IList, NHibernate.Engine.ISessionImplementor)), calling (MethodDesc 08201884 +0 NHibernate.Loader.Loader.InstanceNotYetLoaded(System.Data.IDataReader, Int32, NHibernate.Persister.Entity.ILoadable, NHibernate.Engine.EntityKey, NHibernate.LockMode, System.String, NHibernate.Engine.EntityKey, System.Object, System.Collections.IList, NHibernate.Engine.ISessionImplementor))
...

所以,我已经查看了coreclr的源代码并发现,在第一步gc_heap::create_bgc_thread启动了一个工作线程并等待(INFINITE)直到这个sthead将被启动:

#else // FEATURE_REDHAWK

    Thread* current_bgc_thread;

    gh->bgc_thread = SetupUnstartedThread(FALSE);
    if (!(gh->bgc_thread))
    {
        goto cleanup;
    }

    current_bgc_thread = gh->bgc_thread;
    if (!current_bgc_thread->CreateNewThread (0, &(gh->bgc_thread_stub), gh))
    {
        goto cleanup;
    }

    current_bgc_thread->SetBackground (TRUE, FALSE);

    // wait for the thread to be in its main loop, this is to detect the situation
    // where someone triggers a GC during dll loading where the loader lock is
    // held.
    current_bgc_thread->StartThread();

#endif // FEATURE_REDHAWK

    {
        dprintf (2, ("waiting for the thread to reach its main loop"));
        // In chk builds this can easily time out since
        // now we need to set the thread up into a managed thead. 
        // And since it's a managed thread we also need to make sure that we don't
        // clean up here and are still executing code on that thread (it'll
        // trigger all sorts of asserts.
        //DWORD res = gh->background_gc_create_event.Wait(20,FALSE);
        DWORD res = gh->background_gc_create_event.Wait(INFINITE,FALSE);
        if (res == WAIT_TIMEOUT)

因此,看起来create_bgc_thread等待一个线程无法恢复(Thread::StartThread只调用::ResumeThread)。

在倾销堆中有一条奇怪的线,我真的不明白:

0a26e83c 74df70ea clr!Thread::StartThread+0x71, calling clr!_EH_epilog3

这意味着什么?它是clr的异常/崩溃吗?

1 个答案:

答案 0 :(得分:1)

这是一个可能有助于您理解的Microsoft doc on prologs and epilogs

基于此blog on Microsoft exception handling看起来_EH_epilog3是内置的epilog函数。

我的猜测是,该线程可能抛出了一个未处理的异常?