AppInit_DLLs 에 winmm.dll이 어인일로.

최근에 XP machine Application silently shutdown 되는 현상이 발생하여 Debugger 걸고 확인해 적이 있었다. 마치 Program 정상적으로 올라오기도 전에 Task manager에서 Process이름만 보였다 사라지는 경우라, program 실행되지 않은 것인가 의심할 수도 있는 , Crash 의해 Shut Down임을 Debugger Break 통해 확인할 있었다.

 

0:000> kbL
ChildEBP RetAddr  Args to Child
0012d55c 7c93104b 00fc6540 77f7a00d 77fc6540 ntdll!RtlpWaitForCriticalSection+0x8c
0012d564 77f7a00d 77fc6540 3f2cfa2c 3f2cfd70 ntdll!RtlEnterCriticalSection+0x46
0012d574 77f7a826 00000000 00000000 00000000 advapi32!WmipCreateHeap+0x10
0012d588 3f25cbe3 3f294c87 3f2cfd70 3f25ce44 advapi32!RegisterTraceGuidsA+0x1d
0012d5c0 3f25cdbf 3f25ce64 00000001 00000000 wininet!WppInitUm+0x3d
0012d5d8 3f23167f 3f230000 00000001 00000000 wininet!DllMain+0x5c
0012d638 7c9311a7 3f230000 00000001 00000000 wininet!__DllMainCRTStartup+0xdb
0012d658 7c94cbab 3f231784 3f230000 00000001 ntdll!LdrpCallInitRoutine+0x14
0012d760 7c946178 00000000 c0150008 0012e5b4 ntdll!LdrpRunInitializeRoutines+0x344
0012da0c 7c9462da 00000000 00143f58 0012dd00 ntdll!LdrpLoadDll+0x3e5
0012dcb4 7c801bb9 00143f58 0012dd00 0012dce0 ntdll!LdrLoadDll+0x230
0012dd1c 7c801d6e 7ffddc00 00000000 00000000 kernel32!LoadLibraryExW+0x18e
0012dd30 7c801da4 10001c54 00000000 00000000 kernel32!LoadLibraryExA+0x1f
0012dd4c 1000428a 10001c54 10006c46 0012dec4 kernel32!LoadLibraryA+0x94
WARNING: Frame IP not in any known module. Following frames may be wrong.
0012dd98 7c940895 719e0000 00000000 0012de74 0x1000428a
0012ddb8 0012de14 0012de1a 000011ed 00000000 ntdll!RtlImageDirectoryEntryToData+0x57
0012de1c 7c8099f0 0012deb4 100065c4 00000004 0x12de14
0012dec4 003c5bd4 003c1618 00000001 00000000 kernel32!LocalAlloc+0x168
0012def8 7c94d555 003c0310 7c94d5a4 00000008 tfdsy+0x5bd4
0012df0c 7c9311a7 003c0000 00000001 00000000 ntdll!LdrpCheckNxIncompatibleDllSection+0x84
0012df2c 7c94cbab 003c6de8 003c0000 00000001 ntdll!LdrpCallInitRoutine+0x14
0012e034 7c946178 00000000 c0150008 0012f228 ntdll!LdrpRunInitializeRoutines+0x344
0012e2e0 7c9462da 00000000 00143798 0012e5d4 ntdll!LdrpLoadDll+0x3e5
0012e588 7c801bb9 00143798 0012e5d4 0012e5b4 ntdll!LdrLoadDll+0x230
0012e5f0 7c80ae5c 0012e61c 00000000 00000000 kernel32!LoadLibraryExW+0x18e
0012e604 76af338c 0012e61c 7c9310ed 76b10160 kernel32!LoadLibraryW+0x11
0012e720 76af3024 0012eb20 76b10668 76b10650 winmm!LoadAliasedLibrary+0x106
0012e750 76af2e8e 0012eb20 00000000 0012e780 winmm!InternalLoadDriver+0xdb
0012e884 76af2e53 0012eb20 00000000 00000000 winmm!InternalOpenDriver+0x32
0012e89c 76af388a 0012eb20 00000000 00000000 winmm!DrvOpen+0x15
0012eb10 76af41a5 0012eb20 76b109bc 0069006d winmm!mmDrvOpen+0x46
0012eb30 76af4129 00000001 00000000 76af2b69 winmm!MidiInit+0x30
0012eb40 76af4042 00000001 0012eb94 76af2b69 winmm!InitDevices+0xb8
0012eb74 76af2b9c 76af0000 0012eba0 7c9311a7 winmm!DllProcessAttach+0xe4
0012eb80 7c9311a7 76af0000 00000001 00000000 winmm!_DllInstanceInit+0xb3
0012eba0 7c94cbab 76af2b69 76af0000 00000001 ntdll!LdrpCallInitRoutine+0x14
0012eca8 7c946178 00000000 c0150008 00000000 ntdll!LdrpRunInitializeRoutines+0x344
0012ef54 7c9462da 00000000 001435f8 0012f248 ntdll!LdrpLoadDll+0x3e5
0012f1fc 7c801bb9 001435f8 0012f248 0012f228 ntdll!LdrLoadDll+0x230
0012f264 7c80ae5c 0012f2cc 00000000 00000000 kernel32!LoadLibraryExW+0x18e
0012f278 77d25446 0012f2cc 77e261c1 7ffdd000 kernel32!LoadLibraryW+0x11
0012f304 77cfa108 00000000 00000000 7c94a703 user32!LoadAppDlls+0x168
0012f444 77cfa133 7c93eae3 0012f458 00000000 user32!ClientThreadSetup+0x1e8
0012f448 7c93eae3 0012f458 00000000 77e267c4 user32!__ClientThreadSetup+0x5
0012f454 77e267c4 77e26553 0012f5a8 0012f9f0 ntdll!KiUserCallbackDispatcher+0x13
0012f464 77cff774 77cf0000 00000001 0012fd30 gdi32!NtGdiInit+0xc
0012f9f0 7c9311a7 77cf0000 00000001 0012fd30 user32!_UserClientDllInitialize+0x315
0012fa10 7c94cbab 77cff518 77cf0000 00000001 ntdll!LdrpCallInitRoutine+0x14
0012fb18 7c95173e 0012fd30 7ffdd000 7ffde000 ntdll!LdrpRunInitializeRoutines+0x344
0012fc94 7c951639 0012fd30 7c930000 0012fce0 ntdll!LdrpInitializeProcess+0x1131
0012fd1c 7c93eac7 0012fd30 7c930000 00000000 ntdll!_LdrpInitialize+0x183
00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7 

 

0:000> du 0012e61c
0012e61c  "C:\WINDOWS\tfdsy.tmp"

 

0:000> du 0x0012eb20
0012eb20  "midi9"

 

Callstack 마치 Wininet DLL에서 사용하는 Critical Section Object Heap Corruption 의한 Access Violation(AV) 으로 보이지만 사실은 전에 없는 모듈인 tfdsy.tmp file load 의해 유도된 AV 맞다. 상위의 이름 모를 tmp file(혹은, .dat .bak 등등의 임의의 확장자일 수도 있는 , 이들은 사실 DLL이나 실행 파일일 있다.) winmm!LoadAliasedLibrary 의해서 load되는 , 사실 wimm.dll load 되는 것이 해당 머신의 registry key값인 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows AppInit_DLLs winmm.dll 설정되어 있기 때문에 기본적인 DLL injection 매카니즘에 의해서 load 되는 것이며, 이로 인하여 문제가 있는 모듈(여기서는 tfdsy.tmp file) 역시 load 되어  Application Crash 유발하게 된다. 해당 Issue 문제 되는 것이 AppInit_DLLs Key 의한 DLL injection 경우는 대부분의 process DLL Injection 시킬 사용하는 방법이기 때문에 일부 Application 아닌 백신 프로그램이나 OS 중요한 프로세스에도 Injection 되어 Crash 있다는 데에 이슈가 된다.

 

확인 결과 AppInit_DLLs 레지스트리 뿐만이아니라 LoadAppInit_DLLs에도 1 설정되어 있으며  이들의 값을 삭제하여도 다시 복원되며, 상위의 없는 모듈, System32 시스템 폴더에 위치하는 , 역시 삭제하여도 복원되는 악성 코드임으로 밝혀졌다.

 

이러한 악성코드는 최신의 백신프로그램을 매뉴얼 업데이트하여 치료할 있으므로, 문제가 되기 전에 확인한다면 문제되지 않을 것이다. (간혹, HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\WINDOWS NT\CurrentVersion\DRIVERS32 "MIDI9 = 랜덤 " 삭제한 후 간혹, tmp file이 삭제되거나 해서 문제를 피해가는 경우가 있다. )

by 강세윤 | 2009/12/02 15:12 | Windows debugging | 트랙백 | 덧글(0)
음식에 대한 짧은 생각

음식 하나 만드는 데도 정성이 필요하다. 그 정성은 먹는 사람이 알고 느끼게 된다. 예를 들어, 만두 하나를 쪄서 먹더라도 다소 차이가 있다. 요즘, 대형 마트에 가면 흔히 살 수 있는 냉동만두가 있는데 이를 다시마와 멸치 그리고, 양파를 넣고 끊인 물에 적절히 간장으로 간해서 만든 육수에 넣고, 조금 끓인 후에 파를 듬성듬성 썰어 넣고 조금 더 끓여 먹으면 괜찮은 만두국이 된다. 근데, 대형 마트에 있는 만두 말고, 두부나 부추 숙주 돼지고기 등으로 다져진 속에 맛난 만두피로 빚은 손 만두를 쪄 먹거나 국으로 해서 먹으면 그 맛이 냉동만두와 비교하랴. 하물며, 대형 마트산 냉동만두를 국 끓이기는커녕 찌기도 귀찮아 전자렌지에 몇 분 데펴서 수분 빠진 만두를 찐 만두라 먹으며 배고픔이 반찬이 되지 않는 한, 입에 들어 갔을 때, 입안에 만두가 쩍 달라 붙어서 넘기는 데도 힘이 들고, 씹는 데로 비린 돼지고기 냄새를 제거하기 위해 너무 많이 첨가한 후추나 인공감미료의 푸석푸석한 맛이 입맛을 버리게 될지도 모른다.

 

공자는 고기에 알맞은 양념이 되어 있지 않거나 또는 잘게 썰어있지 않거나, 심지어 고기 빛깔이 좋지 않을 때 젓가락을 들지 않았고, 쌀은 아주 새 하얀 것이 아니면 입에 대지 않았다고 한다. 물론, 이러한 음식 투정은 일반적으로 생각해도 다소 심한 것 같은 데, 그 만큼 음식이 신체에 끼치는 부분을 크게 여겼을 수도 있다. 요즘 누가 공자와 같은 음식 투정을 집에서 할 수 있겠느냐 마는 조금 다르게 본다면 음식을 섭취하여 대단히 만족하고 배가 불렀을 때 그 어떤 세상의 불평 불안이 나를 괴롭힐 수 있겠는가를 느껴보면 달라진다. 그 순간만은 행복 그 자체일 것이다. 공자가 그러한 음식만 입에 댄 것처럼 요즘 세상에 누구에게 그것을 바랄 수 있을 까. 나는 오히려 그러한 누구를 찾기 보다, 스스로 음식을 만드는 기쁨을 느껴 보는 것이 바람직하지 않을 까 한다. 음식을 먹는 즐거움 만큼 내가 좋아하는 음식을 만드는 노동의 기쁨 또한 대단하다고 생각한다. 나는 간혹 샌드위치를 만들어 먹는 데, 넣는 재료에 따라서 달리 맛을 느끼는 재미가 쏠쏠하고 그다지 큰 요리 기술이 필요하지 않음에도 불구하고 약간의 주의가 맛을 좌지우지하는 것이라 흥미롭다. 조금 귀찮지만, 흔한 베이컨을 굽거나 햄을 물에 삶아 준비하고, 달걀을 풀어 후라이팬에 부쳐 식빵크기에 맞게 또한 준비하며, 잘 씻은 토마토는 칼로 갈라 속의 물기를 거의 빼고 한입에 먹기 좋은 크기로 포를 뜨듯이 잘라 만든 후에 살짝 구운 빵이 식기 전에 딸기잼으로 한 면을 발라서 그 위에 계란 부친 것을 올리고 계란이 따끈할 때, 치즈를 올려 녹이고, 그 위에 토마토 썬 것을 올려 캐첩과 머스타드를 섞어 뿌리고 그리고, 햄이나, 베이컨을 그 위에 올려 빵으로 살짝 덮어서 만든 후 빵을 반쯤 썰어 우유와 같이 먹는 다. 근데, 하나의 샌드위치를 만들 때와 여러 개의 샌드위치를 동시에 만들 때 그 맛이 다르다. 간혹, 토마토의 물기가 빵 아래로 흘러내리는 가 하면, 캐첩과 머스타드의 진함이 달라 토마토나 계란 등의 맛을 먹어버리는 경우가 다소 있으며 적절한 시점에 후라이팬에 구운 빵을 사용하지 않으면 샌드위치 내용물에 따라 빵이 눅눅해지거나 또는 빵이 타서 먹기에 입안이 불편할 정도로 거칠어 질수도 있다. 이는 여러 개의 샌드위치를 만드느냐 집중하지 못한 까닭이다. 음식을 만들 때의 정성과 주의는 먹을 때의 행복을 좌지우지 하므로 중요하지만 그보다 중요한 것은 만드는 즐거움이 있어야 먹을 때 역시 즐겁고 행복하다는 것이다.

by 강세윤 | 2009/11/26 13:11 | 정리되지 않은 생각 | 트랙백 | 덧글(1)
IE Embedded UserControl안에서 TcpClient를 사용하는 경우, DeadLock현상이 발생할 수도 있다.

Internet Explorer Embedding UserControl안에서 Syetem.Net.Sockets.TcpClient를 사용하는 경우, .NET Framework 2.0 SP1이후 Version에서 Hang 현상이 발생할 수 있다
 

이는 Internet Explorer환경이 Proxy Server를 이용하여 URL redirect가 되는 경우, redirect되는 URL%20 등과 같은 International Characters가 포함되었다면, 이것이 원인이 될 수 있으며 해당 어셈블리가 초기화되는 시점에 다음과 같은 코드를 추가함으로써 이 문제를 피해갈 수 있다.

 

public UserControl1()

{

            Type uriType = typeof(Uri);

 

            FieldInfo UriConfigInitField;

            UriConfigInitField = uriType.GetField("s_ConfigInitialized",

                BindingFlags.Static | BindingFlags.NonPublic);

            UriConfigInitField.SetValue(uriType, true);

 

            FieldInfo IriParsingField = uriType.GetField("s_IriParsing",

                BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField);

            IriParsingField.SetValue(uriType, false);

           

            FieldInfo IdnScopeField = uriType.GetField("s_IdnScope",

                BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField);

            IdnScopeField.SetValue(uriType, UriIdnScope.None);

//. . .

}

private void button1_Click(object sender, EventArgs e)
{
    string hostname = "...";
    int port = 0xbb7;

    TcpClient client = new TcpClient(hostname, port);
. . .
}
 

이는 다음의 Callstack Redirect URL International 문자열이 존재하는 지를 가지고 verification할 수 있다.

 

0:003> !clrstack
OS Thread Id: 0xc70 (3)
ESP       EIP    
01dcec94 7c90e514 [GCFrame: 01dcec94]
01dced68 7c90e514 [HelperMethodFrame_1OBJ: 01dced68] System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object)
01dcedcc 792cbd18 System.Threading.Monitor.Wait(System.Object, Int32, Boolean)
01dceddc 028d00d8 System.Configuration.ClientConfigurationSystem.EnsureInit(System.String)  <<<<<
01dcee18 0751ffcc System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(System.String)
01dcee24 0751ff64 System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(System.String)
01dcee38 0751db70 System.Configuration.ConfigurationManager.GetSection(System.String)
01dcee44 0751db21 System.Configuration.PrivilegedConfigurationManager.GetSection(System.String)
01dcee54 03366add System.Configuration.UriSectionInternal.GetSection()
01dcee88 03366837 System.Uri.GetConfig(System.UriIdnScope ByRef, Boolean ByRef)
01dceed4 0336671d System.Uri.InitializeUriConfig()
01dcef00 05fd160a System.Uri.InitializeUri(ParsingError, System.UriKind, System.UriFormatException ByRef)
01dcef34 0336663a System.Uri.CreateThis(System.String, Boolean, System.UriKind)
01dcef54 03366511 System.Uri.CreateUri(System.Uri, System.String, Boolean)
01dcef70 0336647b System.Uri..ctor(System.Uri, System.String)
01dcef84 03365e3a System.Net.HttpWebRequest.CheckResubmit(System.Exception ByRef)
01dcefc8 033631c8 System.Net.HttpWebRequest.DoSubmitRequestProcessing(System.Exception ByRef)
01dceffc 03362fcb System.Net.HttpWebRequest.ProcessResponse()
01dcf034 03361a08 System.Net.HttpWebRequest.SetResponse(System.Net.CoreResponseData)
01dcf070 033618c4 System.Net.HttpWebRequest.CheckWriteSideResponseProcessing()
01dcf080 02babb1a System.Net.HttpWebRequest.EndSubmitRequest()
01dcf0b8 02bab65c System.Net.HttpWebRequest.SetRequestSubmitDone(System.Net.ConnectStream)
01dcf0c8 02bab359 System.Net.Connection.CompleteConnection(Boolean, System.Net.HttpWebRequest)
01dcf118 02ba8486 System.Net.Connection.CompleteStartConnection(Boolean, System.Net.HttpWebRequest)
01dcf164 02ba8206 System.Net.Connection.CompleteStartRequest(Boolean, System.Net.HttpWebRequest, System.Net.TriState)
01dcf194 02ba7b10 System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest)
01dcf1dc 02ba5fb7 System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest, System.String)
01dcf214 02b8f055 System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint)
01dcf240 02b89de0 System.Net.HttpWebRequest.GetResponse()
01dcf280 02b8d333 System.Net.AutoWebProxyScriptEngine.DownloadAndCompile(System.Uri, System.Net.AutoWebProxyScriptWrapper ByRef, Int32 ByRef)
01dcf2f0 02b8c971 System.Net.AutoWebProxyScriptEngine.EnsureEngineAvailable(Int32 ByRef)
01dcf308 02b8baed System.Net.AutoWebProxyScriptEngine.GetProxies(System.Uri, Boolean, System.Net.AutoWebProxyState ByRef, Int32 ByRef)
01dcf350 02b8b9a5 System.Net.WebProxy.GetProxiesAuto(System.Uri, System.Net.AutoWebProxyState ByRef, Int32 ByRef)
01dcf36c 02b8b8ee System.Net.ProxyScriptChain.GetNextProxy(System.Uri ByRef)
01dcf380 02b8b7f0 System.Net.ProxyChain+ProxyEnumerator.MoveNext()
01dcf3b4 02b8aa36 System.Net.ServicePointManager.FindServicePoint(System.Uri, System.Net.IWebProxy, System.Net.ProxyChain ByRef, System.Net.HttpAbortDelegate ByRef, Int32 ByRef)
01dcf3f4 02b8a90e System.Net.HttpWebRequest.FindServicePoint(Boolean)
01dcf424 02b89dd6 System.Net.HttpWebRequest.GetResponse()
01dcf464 02b89b70 System.Net.WebClient.GetWebResponse(System.Net.WebRequest)
01dcf470 02b89b16 System.Net.WebClient.DownloadBits(System.Net.WebRequest, System.IO.Stream, System.Net.CompletionDelegate, System.ComponentModel.AsyncOperation)
01dcf494 02b86f17 System.Net.WebClient.DownloadDataInternal(System.Uri, System.Net.WebRequest ByRef)
01dcf4c4 02b86d5f System.Net.WebClient.DownloadData(System.Uri)
01dcf4f8 02b846c2 System.Net.WebClient.DownloadData(System.String)
01dcf504 028d2231 System.Configuration.ClientConfigurationHost.OpenStreamForRead(System.String)
01dcf538 028d0e29 System.Configuration.BaseConfigurationRecord.InitConfigFromFile()
01dcf620 0751f162 System.Configuration.BaseConfigurationRecord.Init(System.Configuration.Internal.IInternalConfigRoot, System.Configuration.BaseConfigurationRecord, System.String, System.String)
01dcf87c 0751e105 System.Configuration.RuntimeConfigurationRecord.Create(System.Configuration.Internal.InternalConfigRoot, System.Configuration.Internal.IInternalConfigRecord, System.String)
01dcf890 028d051e System.Configuration.Internal.InternalConfigRoot.GetConfigRecord(System.String)
01dcf8e4 028d019f System.Configuration.ClientConfigurationSystem.EnsureInit(System.String)   <<<<<
01dcf920 0751ffcc System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(System.String)
01dcf92c 0751ff64 System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(System.String)
01dcf940 0751db70 System.Configuration.ConfigurationManager.GetSection(System.String)
01dcf94c 0751db21 System.Configuration.PrivilegedConfigurationManager.GetSection(System.String)
01dcf95c 0751dacd System.Diagnostics.DiagnosticsConfiguration.GetConfigSection()
01dcf964 0751d8f9 System.Diagnostics.DiagnosticsConfiguration.Initialize()
01dcf990 0751d812 System.Diagnostics.DiagnosticsConfiguration.get_Sources()
01dcf99c 0751d658 System.Diagnostics.TraceSource.Initialize()
01dcf9cc 0751d2f8 System.Net.Logging.InitializeLogging()
01dcf9fc 0751d1bf System.Net.Logging.get_On()
01dcfa00 0751d01c System.Net.Sockets.TcpClient..ctor(System.String, Int32)
01dcfa30 0751ba1f Simple.UserControl1.button1_Click(System.Object, System.EventArgs)
01dcfaa4 0751a3a7 System.Windows.Forms.Control.OnClick(System.EventArgs)
01dcfab8 0751b992 System.Windows.Forms.Button.OnClick(System.EventArgs)
01dcfac8 0751b87c System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs)
01dcfae4 0751a235 System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)
01dcfb74 05fdae1f System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
01dcfb78 0613a84d [InlinedCallFrame: 01dcfb78]
01dcfc08 0613a6c3 System.Windows.Forms.Button.WndProc(System.Windows.Forms.Message ByRef)
01dcfc14 05fda8c0 System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)
01dcfc1c 05fda898 System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
01dcfc30 05fda6e8 System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
01dcfd4c 03732714 [ContextTransitionFrame: 01dcfd4c]

 

by 강세윤 | 2009/11/23 14:51 | Windows debugging | 트랙백 | 덧글(0)
다중(Multi) Threads 환경에서 static type을 사용하는 것에 대한 우려

.." Use the static modifier to declare a static member, which belongs to the type itself rather than to a specific object. The static modifier can be used with classes, fields, methods, properties, operators, events and constructors, but cannot be used with indexers, destructors, or types other than classes. " ... http://msdn.microsoft.com/en-us/library/98f28cdx(VS.80).aspx

 

하지만, static keyword Thread Safe와는 친하지 않기 때문에 Multiple users Threads 환경에서 race condition에 따라 Data Corruption되거나 NullReferenceException이 발생할 수도 있다.

 

0:031> kb

ChildEBP RetAddr  Args to Child             

0d4ff0d4 7923b543 e0434f4d 00000001 00000000 kernel32!RaiseException+0x53

0d4ff12c 7923b4c6 069703b0 00000000 0d4ff388 mscorsvr!RaiseTheException+0xa0

0d4ff154 7923b47a 069703b0 00000000 0d4ff398 mscorsvr!RealCOMPlusThrow+0x48

0d4ff164 79239c8c 069703b0 0000002b 00000000 mscorsvr!RealCOMPlusThrow+0xd

0d4ff398 792b718e 0000002b 00000000 00000000 mscorsvr!CreateMethodExceptionObject+0x67b

0d4ff42c 792b71b2 80004003 00000000 00000000 mscorsvr!RealCOMPlusThrowHRWorker+0xb9

0d4ff448 792b731c 80004003 00000000 00000000 mscorsvr!RealCOMPlusThrowHRWorker+0x15

0d4ff4d4 792a8552 80004003 00000000 0d4ff514 mscorsvr!RealCOMPlusThrowHR+0x168

0d4ff4e8 0268435d 00000000 00000000 80004003 mscorsvr!Interop::ThrowExceptionForHR+0x3a

WARNING: Frame IP not in any known module. Following frames may be wrong.

0d4ff660 791f6049 00000001 0d4ff69c 791f609d 0x268435d

0d4ff66c 791f609d 0cafa2d8 0695800c 00000000 mscorsvr!CTPMethodTableCallTargetHelper+0xf

0d4ff69c 791fa7f8 0cafa2d8 0695800c 00000000 mscorsvr!CTPMethodTable::CallTarget+0x4e

0d4ff6c0 791b2682 0cb06e5c 00000000 00000001 mscorsvr!CRemotingServices::CreateProxyOrObject+0x5f

0d4ff730 791b273c 0cb06e5c 0caff013 00000000 mscorsvr!AppDomain::GetOffsetOfSlotsCount+0xa0

0d4ff74c 791b7f92 0d4ff864 791bdd4e 0d4ff7a0 mscorsvr!JIT_NewCrossContext+0x3a

0d4ff754 791bdd4e 0d4ff7a0 00000000 0d4ff778 mscorsvr!CallDescrWorker+0x30

0d4ff864 791d5bd5 00b07f53 026e8a10 024547a0 mscorsvr!MethodDesc::CallDescr+0x1b8

0d4ff88c 79236659 0d4ff8a8 024547a0 0d4ffc8c mscorsvr!MethodDesc::Call+0x8e

0d4ff8b8 792cec0a 069700c8 0d4ff934 02683c9a mscorsvr!CallDefaultConstructor+0x10c

0d4ff8c4 02683c9a 0d4ff8d0 069700c8 0cafec57 mscorsvr!CRemotingServices::CallDefaultCtor+0xd

 

0:031> !do 069703b0

Name: System.NullReferenceException

 

0:031> !dumpstack -EE

Thread 31

Current frame:

  ChildEBP RetAddr    Caller,Callee

0d4ff51c 0cafd1f5 (MethodDesc 0xcb03410 +0x255 System.EnterpriseServices.Thunk.Proxy.CoCreateObject)

0d4ff548 0cafd107 (MethodDesc 0xcb03410 +0x167 System.EnterpriseServices.Thunk.Proxy.CoCreateObject)

0d4ff600 0cafc0e4 (MethodDesc 0x2643ea0 +0x64 System.Runtime.Remoting.RemotingConfigHandler.IsRemotelyActivatedClientType)

0d4ff608 0cafc6df (MethodDesc 0xcb037d0 +0x1f System.EnterpriseServices.ServicedComponentInfo.SCICachedLookup)

0d4ff610 0cafa8a3 (MethodDesc 0xcb015c8 +0xb3 System.EnterpriseServices.ServicedComponentProxyAttribute.CreateInstance)

0d4ff654 0cafa320 (MethodDesc 0x24fe618 +0x48 System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK)

0d4ff6f0 0caff8f6 (MethodDesc 0xcb07600 +0x6e System.EnterpriseServices.RWHashTableEx.Put)

0d4ff738 0caff013 (MethodDesc 0xcb01710 +0x2b ttt.obj.objMTS..ctor)

0d4ff748 0d50071e (MethodDesc 0xcb07f58 +0x6 ttt.objMain.obj_11..ctor)

0d4ff8d0 0cafec57 (MethodDesc 0x21c9240 +0x7f System.Runtime.Remoting.Proxies.RealProxy.InitializeServerObject)

0d4ff8f4 0cafec95 (MethodDesc 0x21c9240 +0xbd System.Runtime.Remoting.Proxies.RealProxy.InitializeServerObject)

0d4ff920 0cafe77d (MethodDesc 0xcb02e88 +0x85 System.EnterpriseServices.ServicedComponentProxy.SetupContext)

0d4ff934 0cafe683 (MethodDesc 0xcb02d28 +0x1b System.EnterpriseServices.ServicedComponentProxy.ConstructServer)

0d4ff940 0cafe441 (MethodDesc 0xcb02bc8 +0x141 System.EnterpriseServices.ServicedComponentProxy..ctor)

0d4ff96c 0cafe0f2 (MethodDesc 0xcb015f8 +0x8a System.EnterpriseServices.ServicedComponentProxyAttribute.System.Runtime.InteropServices.ICustomFactory.CreateInstance)

0d4ff994 0cafdda3 (MethodDesc 0x24fe628 +0x4b System.Runtime.Remoting.Activation.ActivationServices.CreateObjectForCom)

0d4ffc74 0cafdd24 (MethodDesc 0xcb034a0 +0x6c System.EnterpriseServices.Thunk.Proxy.CallFunction)

0d4ffc98 0cafdd24 (MethodDesc 0xcb034a0 +0x6c System.EnterpriseServices.Thunk.Proxy.CallFunction)

0d4ffcc0 0cafdc87 (MethodDesc 0xcb05a28 +0x67 System.EnterpriseServices.Internal.AppDomainHelper.System.EnterpriseServices.Internal.IAppDomainHelper.DoCallback)

 

상위 Callstack NullReferenceException이 발생한 것을 보여주는 데, ttt.obj.objMTS..ctor Constructor에서의 NulLReferenceException이므로, ttt.obj.objMTS 라는 Class의 초기화에서 NullReferenceException이 발생한 것을 알 수 있다. 하지만, 해당 Dump에서는 몇몇의 Thread가 상위의 NullReferenceException이 발생한 Class의 Constructor와 관련이 있다는 것이다. 아래의 callstack은 상위의 NullReferenceException이 발생한 Constructor의 진행과정을 보여주고 있다. 이게 무엇을 의미하는 가.

 

0:030> kb

ChildEBP RetAddr  Args to Child             

0d48f0bc 7943b437 024327c0 02430010 02431e5c mscorjit!Compiler::fgSetStmtSeq+0x38

0d48f0d0 7943b466 02431e5c 0d48f328 02430010 mscorjit!Compiler::fgSetBlockOrder+0x17

0d48f0e0 794311b5 00000000 02430010 0d48f13c mscorjit!Compiler::fgSetBlockOrder+0x26

0d48f0f0 79431581 0d48f204 0d48f380 0d48f1f8 mscorjit!Compiler::compCompile+0xa4

0d48f13c 79431622 00130628 0d48f2dc 0d48f328 mscorjit!Compiler::compCompile+0x1e8

0d48f1c4 794316ac 0d48f2dc 0d48f328 0d48f204 mscorjit!jitNativeCode+0x95

0d48f208 791bfd04 79479124 0d48f2dc 0d48f328 mscorjit!CILJit::compileMethod+0xa2

0d48f250 791b91f4 000e38a0 0d48f2dc 0d48f328 mscorsvr!CallCompileMethodWithSEHWrapper+0x52

0d48f3b8 791b95bf 0cb0bab0 0d48f580 0d48f4bc mscorsvr!JITFunction+0x2c7

0d48f4ec 791b4428 0cb0bab0 0d48f580 00000000 mscorsvr!MakeJitWorker+0x2c0

0d48f5d8 791b453f 00000000 0d48f8ec 0d48f614 mscorsvr!MethodDesc::DoPrestub+0x4d3

0d48f5f0 02102f76 0d48f614 00000000 029203b0 mscorsvr!PreStubWorker+0x42

WARNING: Frame IP not in any known module. Following frames may be wrong.

00000000 00000000 00000000 00000000 00000000 0x2102f76

 

0:030> !dumpstack -EE

Thread 30

Current frame:

  ChildEBP RetAddr    Caller,Callee

0d48f61c 0d509747 (MethodDesc 0xcb0baa0 +0x17 System.Xml.XPath.XPathParser.ParseAdditiveExpr)

0d48f634 0d50968f (MethodDesc 0xcb0ba90 +0x17 System.Xml.XPath.XPathParser.ParseRelationalExpr)

0d48f64c 0d509537 (MethodDesc 0xcb0ba80 +0x17 System.Xml.XPath.XPathParser.ParseEqualityExpr)

0d48f664 0d509332 (MethodDesc 0xcb0ba70 +0x12 System.Xml.XPath.XPathParser.ParseAndExpr)

0d48f678 0d5092ba (MethodDesc 0xcb0ba60 +0x12 System.Xml.XPath.XPathParser.ParseOrExpr)

0d48f68c 0d5086d0 (MethodDesc 0xcb0ba30 +0x38 System.Xml.XPath.XPathParser.ParseXPathExpresion)

0d48f698 0d507738 (MethodDesc 0xcb0a3d8 +0x38 System.Xml.XPath.XPathNavigator.Compile)

0d48f6b0 0d5076df (MethodDesc 0xcb0a458 +0x1f System.Xml.XPath.XPathNavigator.Select)

0d48f6c0 0d506e6c (MethodDesc 0xc8609e8 +0x24 System.Xml.XmlNode.SelectSingleNode)

0d48f6e4 0d500391 (MethodDesc 0xcb06a98 +0x79 aaa.ClassMain.Config.xmlLoad)

0d48f728 0caff1d1 (MethodDesc 0xcb06a38 +0x79 aaa.ClassMain.Config..ctor)

0d48f730 0caff0d0 (MethodDesc 0xcb06a58 +0x28 aaa.ClassMain.Config.GetConfig)

0d48f738 0cafeff9 (MethodDesc 0xcb01710 +0x11 ttt.obj.objMTS..ctor)

0d48f748 0caff08e (MethodDesc 0xcb01820 +0x6 ttt.objMain.obj_Comp..ctor)

0d48f8d0 0cafec57 (MethodDesc 0x21c9240 +0x7f System.Runtime.Remoting.Proxies.RealProxy.InitializeServerObject)

0d48f8f4 0cafec95 (MethodDesc 0x21c9240 +0xbd System.Runtime.Remoting.Proxies.RealProxy.InitializeServerObject)

0d48f920 0cafe77d (MethodDesc 0xcb02e88 +0x85 System.EnterpriseServices.ServicedComponentProxy.SetupContext)

0d48f934 0cafe683 (MethodDesc 0xcb02d28 +0x1b System.EnterpriseServices.ServicedComponentProxy.ConstructServer)

0d48f940 0cafe441 (MethodDesc 0xcb02bc8 +0x141 System.EnterpriseServices.ServicedComponentProxy..ctor)

0d48f96c 0cafe0f2 (MethodDesc 0xcb015f8 +0x8a System.EnterpriseServices.ServicedComponentProxyAttribute.System.Runtime.InteropServices.ICustomFactory.CreateInstance)

0d48f994 0cafdda3 (MethodDesc 0x24fe628 +0x4b System.Runtime.Remoting.Activation.ActivationServices.CreateObjectForCom)

0d48fc74 0cafdd24 (MethodDesc 0xcb034a0 +0x6c System.EnterpriseServices.Thunk.Proxy.CallFunction)

0d48fc98 0cafdd24 (MethodDesc 0xcb034a0 +0x6c System.EnterpriseServices.Thunk.Proxy.CallFunction)

0d48fcc0 0cafdc87 (MethodDesc 0xcb05a28 +0x67 System.EnterpriseServices.Internal.AppDomainHelper.System.EnterpriseServices.Internal.IAppDomainHelper.DoCallback)

 

Callstack만 봐서는 문제가 없어 보일 수 있다. 단지, ttt.obj.objMTS..ctor 가 호출되는 2개의 Threads를 본 것이기 때문이다. 하지만, 여기서 ttt.obj.objMTS class Constructor안에서 호출되는 aaa.ClassMain.Config.GetConfig function을 들여다 보면, 다음과 같다.

 

.method public hidebysig static class aaa.ClassMain.Config.GetConfig

        GetConfig() cil managed

{

  // Code size       23 (0x17)

  .maxstack  1

  IL_0000:  ldsfld     class aaa.ClassMain.Config aaa.ClassMain.Config::self

  IL_0005:  brtrue.s   IL_0011

  IL_0007:  newobj     instance void aaa.ClassMain.Config::.ctor()

  IL_000c:  stsfld     class aaa.ClassMain.Config aaa.ClassMain.Config::self

  IL_0011:  ldsfld     class aaa.ClassMain.Config aaa.ClassMain.Config::self

  IL_0016:  ret

} // end of method Config::GetConfig

 

 

.field private static class aaa.ClassMain.Config self

 

, aaa.ClassMain.Config.GetConfig static function이며, 그 보다, 그 안에서 Initialize 되는 aaa.ClassMain.Config Class self 라는 static variable assign 이 된다. 물론, 예상대로 aaa.ClassMain.Config Config File XML data load 하여 parsing 및 저장하여 가지고 있는 개체이다. 하지만, 이러한 data 들은 결코 Thread-safe 하지 않는 상태로 Multiple Threads에 의해서 접근이 가능하다는 것이며, 이러한 data의 초기화 시점에 race condition이 발생한다는 데 있다. 상위의 Callstack (System.EnterpriseServices.Thunk.Proxy.CoCreateObject )을 보면, 예상할 수 있겠지만, 이는 COM+ 혹은 Enterprise Services Application Call이며, Object Pooling과 같은 구조의 Component 초기화는 그러한 위험성을 내포하고 있다.

 

이와 같은 상황에 대해서 문서 http://support.microsoft.com/kb/893666/en-us " Troubleshooting ASP.NET applications with the use of static keywords" 에서는 여러 가지 우려한 시나리오를 언급하고 있다. 이것도 그 중 하나일 것이다. 

 

상위의 문제를 해결하기 위해서는 우선적으로 Thread-Safe 하게 접근하는 것이 우선적일 것이다. Static Keyword 를 사용하지 않는 것도 필요하다면 고려할 수 있지만, Data Locking이나 Synchronization 을 고려한 코드의 일부 수정으로써 문제를 풀어나가는 것도 고려해 볼 수 있지 않나 본다.

by 강세윤 | 2009/11/17 16:02 | Windows debugging | 트랙백 | 덧글(0)
행복의 조건

모처럼 회사 동료의 결혼식에서 주례사의 말씀을 찬찬히 들어볼 기회가 있었는데, 시작이 돌아가신 전대통령의 일기에 언급된 인생은 아름다고, 역사는   이었다. 이어서 이어지는 돌아가신 박경리선생님의 말씀도.. 역시 같은 맥락인 인생은 너무나도 아름답다는 것이다. 결혼을 통해서 새롭게 시작하는 이들에게는 필요한 말이 아닐까 한다. 물론, 잊지 않고 고달픔이 있을 것이라는 것, 이것을 직시하고 슬기롭게 이겨내는 것도 필요함을 잊지 않으셨다. 사실 기억해보면, 나 같이 아무 생각 없이 결혼식에 참가하여 다소 지루함을 못 견뎌 주례사의 말씀을 식사 나오기 전까지의 killing time 용으로 경청하는 사람 및 몇몇을 제외하고는 당사자인 분들을 포함해 정신 없이 바쁜 이들에게는 이러한 좋은 어구가 들렸을 까. 여태 수 십 차례 결혼식을 참가했지만, 이렇게 맘에 와 닫는 주례사는 처음이었다. 항상 형식적인 결혼식의 참가와 형식적인 축하 그리고, 한끼를 때우는 욕심 등이 지금까지 나의 태도에 있어서 부끄럽게 만들었다. 죽음 자체는 아무런 의미가 없고.. 인생이 너무나 아름답다. (.. Old and Wise,) 이 말을 이해하기엔 난 아직 어린것 같다.

 

사실 우리가 살아가는 동안 행복하다고 느낄 때에는 사소한 것들조차 기쁨으로 다가오며, 이때에는 누가 뭐라 해도 인생은 아름답다고 느끼지 않을 까. 하지만, 조금이라도 불행하다면, 과연 인생은 아름답다라고 느낄 수 있을 까. 최근에 읽은 러셀의 행복의 정복을 보면, 우리가 왜 불행한가에 대한 언급이 있다. 병이나 배고픔과 같은 기본적인 육체적인 고통을 제외하고라도 정신적으로 만족스럽지 못해서 발생하는 불행의 원인인 즉, 경쟁, 권태, 자극, 피로, 질투, 피해망상, 죄의식 및 대중에 대한 두려움에 대해서는 하나씩 직시하고 언급하였다. 특히 알랭드 보통의 불안에서도 언급된 peer간의 경쟁과 질투는 결코 알면서도 올바로 의식하지 못했던 부분이다. 사실 범접할 수 없던 태생적으로 다른 이와의 비교에서는 질투보다는 체념이 따르기 때문에 포기되는 부분으로 스스로를 괴롭히진 않는 다. 하지만, 지금 같은 만민 평등 시대에서 똑같은 조건에서 태어나고 자랐다고 여기는 주변의 누구는 소위 부동산에, 주식에 일가견이 있어서 지금 시대의 성공의 척도가 되는 재화의 축적을 보란 듯이 했다는 소식만 들어도 그에 따른 질투와 열등감 그리고, 경쟁의식에 피곤하고 불행해진다. 그와 반대로 부에 대해서 끊임없이 추구하여 이들의 부러움을 사는 이들조차 지속적인 부의 축적 및 이에 대한 유지를 위한 쉬지 않는 경쟁 및 피로, 그리고, 경쟁 이후에 오는 권태, 이를 모면하려는 자극, 그 이후의 공허감이 정신을 또한 피폐하게 만든다. 이러한 정신의 상태에서도 인생은 정말 아름다운 것이야 라고 느낄 수 있을 까.

 

상위에 언급한 두 작가는 몇 가지의 불행을 막기 위한 태도에 대해서 언급하고 있는데, 그 중에서 일부 기억에 남는 것으로 지금 그렇게 목매달고 불안해 하고 불행해하는 태도가 원대한 이 우주에서 나라는 존재가 차지하는 것만큼이나 얼마나 보잘것없는 지에 대한 생각의 전환이나, 현실에서의 재화보다 저 세상에서의 재화를 쌓는 부분에 초점을 맞추는 기독교적인 사고가 도움이 될 수 있음을 (내가 이해한 것이 맞다는 가정에) 언급하고 있다. 하지만, 이것이 그리 쉬운 길은 아니다. 물론, 나라는 존재가 이 방대한 우주에 비하면 하잘 것이 없으며, 내가 고민하거나 끊임없이 내 신경을 거슬리며 밤잠을 자지 못하게 하는 그것이 시간이 지나면 왜 그리 고민했었나 할 정도로 미미한 것일 지라도 그 순간에는 대의적인 사고가 되지 않는 것이 인간이다. 또한 기독교적인 인간 역시도 성서를 기반으로 한 이상적인 규율 안에서도 내가 물질적으로 소유하고 있는 부분에 대해서 끊임없이 갈등하는 것이 인간이다. (개인적인 생각으로는) 이것이 인생을 아름답게 만드는 방법이 될 수는 있으나 도 닦는 수준을 원하는 이러한 방법은 끊임없는 자기 최면이나 수양 그리고 노력이 필요하다.

 

그에 비하면, mental tiring과 같은 불행은 이를 잠시라도 잊을 수 있거나 이를 다소 누그러뜨릴 수 있는, 무언가 다 집어 치우고 몰두할 수 있는 취미의 발굴이 더 쉬운 접근법일 수 있다. 더불어, 러셀도 언급했지만, 직업에 대해서, 몰두할 수 있는 취미도 중요하지만, 그와 마찮가지로 몰두할 수 있는 적절한 직업의 선택 역시 중요하다. 요즘, 청년실업의 증가와 함께 이도 역시 쉽지 않은 가운데, 한비아씨가 어느 TV프로그램에서 언급한 이야기가 가슴을 훔친다. 가슴 떨리는, 가슴 벅차게 만드는 일을 찾는 것, 이것이 가장 좋은 방법이 아닐 까 한다. 아마, 인생이 아름답다라고 느끼고 싶다면 …. “무엇이 내 가슴을 뛰게 하는 가에 대한 답변을 낼 수 있으며, 그를 행동으로 옮길 수 있는 용기 ….
 
어느 것을 손에 쥘 수 있을 까, 자기 수양과 용기. 아니면 현명해질 때까지 기다릴 것인가. 인생은 진정으로 아름다운가.

by 강세윤 | 2009/11/08 22:32 | 정리되지 않은 생각 | 트랙백 | 덧글(0)
< 이전페이지 다음페이지 >