다음의 Callstack은 Exception Callstack 중의 하나인데, 언뜻 보면, HRESULT값이 80004003 (잘못된 포인터, System.NullReferenceException)임을 가늠할 수 있다. (굳이 0x06959590에 대한 DumpObject는 필요없을 수 도 ... )
ChildEBP RetAddr Args to Child
0d41f0d4 7923b543 e0434f4d 00000001 00000000 kernel32!RaiseException+0x53
0d41f12c 7923b4c6 06959590 00000000 0d41f388 mscorsvr!RaiseTheException+0xa0
0d41f154 7923b47a 06959590 00000000 0d41f398 mscorsvr!RealCOMPlusThrow+0x48
0d41f164 79239c8c 06959590 0000002b 00000000 mscorsvr!RealCOMPlusThrow+0xd
0d41f398 792b718e 0000002b 00000000 00000000 mscorsvr!CreateMethodExceptionObject+0x67b
0d41f42c 792b71b2 80004003 00000000 00000000 mscorsvr!RealCOMPlusThrowHRWorker+0xb9
0d41f448 792b731c 80004003 00000000 00000000 mscorsvr!RealCOMPlusThrowHRWorker+0x15
0d41f4d4 792a8552 80004003 00000000 0d41f514 mscorsvr!RealCOMPlusThrowHR+0x168
0d41f4e8 0268435d 00000000 00000000 80004003 mscorsvr!Interop::ThrowExceptionForHR+0x3a
WARNING: Frame IP not in any known module. Following frames may be wrong.
0d41f660 791f6049 00000001 0d41f69c 791f609d 0x268435d
0d41f66c 791f609d 0cafa2d8 0695800c 00000000 mscorsvr!CTPMethodTableCallTargetHelper+0xf
0d41f69c 791fa7f8 0cafa2d8 0695800c 00000000 mscorsvr!CTPMethodTable::CallTarget+0x4e
0d41f6c0 791b2682 0cb06e5c 00000000 00000001 mscorsvr!CRemotingServices::CreateProxyOrObject+0x5f
0d41f730 791b273c 0cb06e5c 0caff013 00000000 mscorsvr!AppDomain::GetOffsetOfSlotsCount+0xa0
0d41f74c 791b7f92 0d41f864 791bdd4e 0d41f7a0 mscorsvr!JIT_NewCrossContext+0x3a
0d41f754 791bdd4e 0d41f7a0 00000000 0d41f778 mscorsvr!CallDescrWorker+0x30
0d41f864 791d5bd5 00b068bb 026e8a10 024547a0 mscorsvr!MethodDesc::CallDescr+0x1b8
0d41f88c 79236659 0d41f8a8 024547a0 0d41fc8c mscorsvr!MethodDesc::Call+0x8e
0d41f8b8 792cec0a 06957e50 0d41f934 02683c9a mscorsvr!CallDefaultConstructor+0x10c
0d41f8c4 02683c9a 0d41f8d0 06957e50 0cafec57 mscorsvr!CRemotingServices::CallDefaultCtor+0xd
또 하나 중요한 사실은 Cross boundary Call임을 보여주는 데, JIT_NewCrossContext 즉, Enterprise Services Component가 호출이 정상적으로 이뤄지지 않았음을 보여준다. 이는 분명 COM+에 등록된 Component의 초기화에 실패했음을 역시 보여주고 있다. Manager Callstack을 더 살펴보자.
0:029> !dumpstack -EE
Thread 29
Current frame:
ChildEBP RetAddr Caller,Callee
0d41f51c 0cafd1f5 (MethodDesc 0xcb03410 +0x255 System.EnterpriseServices.Thunk.Proxy.CoCreateObject)
0d41f548 0cafd107 (MethodDesc 0xcb03410 +0x167 System.EnterpriseServices.Thunk.Proxy.CoCreateObject)
0d41f5fc 0cafcd8d (MethodDesc 0xcb03890 +0x7d System.EnterpriseServices.ServicedComponentInfo.HasClassInterface2)
0d41f610 0cafa8a3 (MethodDesc 0xcb015c8 +0xb3 System.EnterpriseServices.ServicedComponentProxyAttribute.CreateInstance)
0d41f654 0cafa320 (MethodDesc 0x24fe618 +0x48 System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK)
0d41f6f0 0caff8f6 (MethodDesc 0xcb07600 +0x6e System.EnterpriseServices.RWHashTableEx.Put)
0d41f738 0caff013 (MethodDesc 0xcb01710 +0x2b AAA.BB.bbCOMPlus..ctor)
0d41f748 0caff1ee (MethodDesc 0xcb068c0 +0x6 AAA.BB.obj11..ctor)
0d41f8d0 0cafec57 (MethodDesc 0x21c9240 +0x7f System.Runtime.Remoting.Proxies.RealProxy.InitializeServerObject)
0d41f8f4 0cafec95 (MethodDesc 0x21c9240 +0xbd System.Runtime.Remoting.Proxies.RealProxy.InitializeServerObject)
0d41f934 0cafe683 (MethodDesc 0xcb02d28 +0x1b System.EnterpriseServices.ServicedComponentProxy.ConstructServer)
0d41f940 0cafe441 (MethodDesc 0xcb02bc8 +0x141 System.EnterpriseServices.ServicedComponentProxy..ctor)
0d41f96c 0cafe0f2 (MethodDesc 0xcb015f8 +0x8a System.EnterpriseServices.ServicedComponentProxyAttribute.System.Runtime.InteropServices.ICustomFactory.CreateInstance)
0d41f994 0cafdda3 (MethodDesc 0x24fe628 +0x4b System.Runtime.Remoting.Activation.ActivationServices.CreateObjectForCom)
0d41fc74 0cafdd24 (MethodDesc 0xcb034a0 +0x6c System.EnterpriseServices.Thunk.Proxy.CallFunction)
0d41fc98 0cafdd24 (MethodDesc 0xcb034a0 +0x6c System.EnterpriseServices.Thunk.Proxy.CallFunction)
0d41fcc0 0cafdc87 (MethodDesc 0xcb05a28 +0x67 System.EnterpriseServices.Internal.AppDomainHelper.System.EnterpriseServices.Internal.IAppDomainHelper.DoCallback)
일단, AAA.BB.bbCOMPlus..ctor Constructor에서 문제가 발생한 것을 보여주는 데, return value를 통해서 진행되고 있는 Assembly code를 살펴볼 필요가 있다.
0:029> ub 0caff013
<Unloaded_mscorwks.dll>+0x22effd:
0cafeffd 47 inc edi
0cafeffe 40 inc eax
0cafefff 60 pushad
0caff000 f5 cmc
0caff001 8bce mov ecx,esi
0caff003 ff15d814b00c call dword ptr [<Unloaded_mscorwks.dll>+0x2314d8 (0cb014d8)]
0caff009 b95c6eb00c mov ecx,offset <Unloaded_mscorwks.dll>+0x236e5c (0cb06e5c)
0caff00e e8ef366b6c call mscorsvr!JIT_NewCrossContext (791b2702)
실질적으로 문제가 발생한 JIT_NewCrossContext 와 연관된 Class를 찾는 것이 목적이다. 상위의 Assembly code를 보면, JIT_NewCrossContext 를 호출하기 이전에 ecx register에 Keep 하는 뭔가가 있음을 확인할 수 있다. 이는 MethodTable 정보이다.
0:029> !dumpmt 0cb06e5c
EEClass : 0x0cb54568
Module : 0x026dc578
Name: xxxx.M.ConfigurationInit
mdToken: 0x02000011 (c:\winnt\assembly\gac\xxxx\1.2.1.4__0230c138d8d9aa19\xxxx.dll)
BaseSize: 0x28
MethodTable Flags : 0x20c0000
Number of IFaces in IFaceMap : 0x4
Interface Map : 0x0cb06f00
Slots in VTable : 30
그러므로, xxxx.M.ConfigurationInit class의 초기화 실패로 인한 잘못된 포인터 오류가 발생했음을 알 수 있다.
사실 상위의 문제를 Fix하기 위해서는 추가적으로 해당 오류가 발생하기 직전에 발생한 1st chance exception들 중에 해당 Class와 연관 있는 exception을 check 해보는 것이 필요 하다. 아니면, 해당 class의 초기화 실패가 코드의 원인일 수도 있기 때문에 code review로써 문제를 해결할 수도 있을 지 모른다.



최근 덧글