Monitor Lock에 의한 hang 현상 debugging

.NET에서 lock 을 목적으로 가장 많이 사용되는 것이 Monitor 가 아닐까 한다. (사실 Multiple Processes사이에서의 Lock이 필요하다면, Mutex를 이용하는 데, 그렇지 않은 경우라면 좀처럼 Mutex를 이용하지 않는 다. 이유는 대략 Monitor에 비해 50여배정도의 low Performance를 나타낸다고 한다. –C# 3.0 in a nutshell에 의하면) 쉽게 Enter/TryEnter Exit 을 통해 Object Lock 을 거는 형태인데, single thread 만 허용하도록 하는 데 목적이 있다. C#에서는 단순하게 lock keyword 를 사용하는 경우가 Monitor를 대신하는 역할을 한다. 그러므로, Exit이 호출되기까지 마치 Critical Section Lock이 걸린 듯하게 된다. 그러므로, Multiple Threaded 환경에서 Exit이 되지 않은 상태에서 Exception이 발생하거나 Thread Drop되는 경우 등등에서 Application Hang이 발생할 수도 있고, 또한 DeadLock이 발생할 수도 있다. 이런 hang 상태일 경우를 메모리dump에서 확인하는 과정은 !syncblk 라는 SOS Extension에서 제공하는 Command를 이용하는 방법이다.

 

0:005> !syncblk

Index SyncBlock MonitorHeld Recursion Owning Thread Info  SyncBlock Owner

   20 0017439c            7         1 0018fe10   a5c  17   08e05824 System.Web.Compilation.BuildManager

 

0:005> !threads

ThreadCount: 14

UnstartedThread: 0

BackgroundThread: 14

PendingThread: 0

DeadThread: 0

Hosted Runtime: no

                                      PreEmptive   GC Alloc           Lock

       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception

   5    1  aac 00151e18   2008220 Enabled  04e843b8:04e84fe8 00191270     1 Ukn

  11    2  69c 00160500      b220 Enabled  00000000:00000000 00157258     0 MTA (Finalizer)

  12    3  ad8 00176250    80a220 Enabled  00000000:00000000 00157258     0 MTA (Threadpool Completion Port)

  13    4  a0c 0018d698   8801220 Enabled  00000000:00000000 00157258     0 Ukn (Threadpool Completion Port)

  14    5  aa4 0018dd30   380b220 Enabled  08e8e38c:08e8efe8 00191270     1 MTA (Threadpool Worker)

  15    6  a94 0018e5f8   8801220 Enabled  00000000:00000000 00157258     0 Ukn (Threadpool Completion Port)

   1    7  948 0018eda0   880a220 Enabled  00000000:00000000 00157258     0 MTA (Threadpool Completion Port)

  16    8  ab4 0018f658   8801220 Enabled  00000000:00000000 00157258     0 Ukn (Threadpool Completion Port)

  17    9  a5c 0018fe10   180b220 Enabled  0ce914f8:0ce92fe8 00191270     4 MTA (Threadpool Worker)

  18    a  ae0 00190918      1220 Enabled  00000000:00000000 00157258     0 Ukn

  19    b  aa8 00192e18   180b220 Enabled  0cecf71c:0ced0fe8 00191270     1 MTA (Threadpool Worker)

  21    c  7a4 001dc8e0   180b222 Disabled 04eec338:04eecfe8 00191270     3 MTA (Threadpool Worker)

  22    d  664 00201108   380b220 Enabled  0ceca780:0cecafe8 00191270     1 MTA (Threadpool Worker)

25    e  500 0021b030   180b220 Enabled  00f10350:00f10814 00191270     1 MTA (Threadpool Worker)

 

!syncblk의 결과값을 보면, 오브젝트 System.Web.Compilation.BuildManager(08e05824) Lock이 걸려있는 상태임을 알 수 있다. 그리고, MonitorHeld 7이라는 것은 (7-1)/2 하여 대략 3개의 Thread가 해당 Object를 접근하려고 기다리는 것임을 알 수 있다. 보통은 아래와 같은 Thread가 접근하는 Thread가 되겠다.

 

ChildEBP RetAddr  Args to Child             

1ce4edec 7c59a23d 00000001 1ce4ee14 00000001 NTDLL!ZwWaitForMultipleObjects+0xb

1ce4ee3c 79f8ead4 1ce4ee14 00000001 00000000 KERNEL32!WaitForMultipleObjectsEx+0xea

1ce4eea4 79f17522 00000001 001743b0 00000000 mscorwks!WaitForMultipleObjectsEx_SO_TOLERANT+0x6f

1ce4eec4 79f17493 00000001 001743b0 00000000 mscorwks!Thread::DoAppropriateAptStateWait+0x3c

1ce4ef48 79f1732f 00000001 001743b0 00000000 mscorwks!Thread::DoAppropriateWaitWorker+0x144

1ce4ef98 79f8ea4d 00000001 001743b0 00000000 mscorwks!Thread::DoAppropriateWait+0x40

1ce4eff4 79e77f50 ffffffff 00000001 00000000 mscorwks!CLREvent::WaitEx+0xf7

1ce4f004 7a0fd9c3 ffffffff 00000001 00000000 mscorwks!CLREvent::Wait+0x17

1ce4f090 7a0fdbbf 00201108 ffffffff 0017439c mscorwks!AwareLock::EnterEpilog+0x94

1ce4f0ac 7a0fdd2a f6aa917c 00201108 00201108 mscorwks!AwareLock::Enter+0x61

1ce4f110 7a094352 ffffffff f6aa91dc 0ceca598 mscorwks!AwareLock::Contention+0x16c

1ce4f1b0 65fb7bcf 79e73dce 08e05824 00000000 mscorwks!JITutil_MonContention+0xa3

1ce4f1f0 65fcf629 00000000 00000000 00000000 System_Web_ni!System.Web.Compilation.BuildManager.GetBuildResultFromCacheInternal(System.String, Boolean, System.Web.VirtualPath, Int64)+0x77

1ce4f26c 65fcf2ef 00000000 00000000 00000000 System_Web_ni!System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(System.Web.VirtualPath)+0x29

1ce4f26c 65fcf266 00000000 00000000 00000000 System_Web_ni!System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(System.Web.VirtualPath, Boolean, Boolean, Boolean)+0x37

1ce4f2a8 66036b2d 00000000 00000000 00000000 System_Web_ni!System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(System.Web.HttpContext, System.Web.VirtualPath, Boolean, Boolean, Boolean)+0x5e

1ce4f2d4 661528dc 00000000 00000000 00000000 System_Web_ni!System.Web.Compilation.BuildManager.GetVPathBuildResult(System.Web.HttpContext, System.Web.VirtualPath)+0x31

1ce4f2d4 69926307 00000000 00000000 00000000 System_Web_ni!System.Web.UI.WebServiceParser.GetCompiledType(System.String, System.Web.HttpContext)+0x2c

1ce4f2ec 65fb94bc 00000000 00000000 00000000 System_Web_Services_ni!System.Web.Services.Protocols.WebServiceHandlerFactory.GetHandler(System.Web.HttpContext, System.String, System.String, System.String)+0x47

1ce4f32c 65fce689 00000000 00000000 00000000 System_Web_ni!System.Web.HttpApplication.MapHttpHandler(System.Web.HttpContext, System.String, System.Web.VirtualPath, System.String, Boolean)+0xb0

 

Monitor Lock의 내부적인 구조는 mscorwks!AwareLock이다. 그러므로, mscorwks!AwareLock::Enter Monitor Lock Enter에 해당한다고 보면 된다. 그리고, !syncblk의 결과에서 owning threadLock안에 들어가 있는 Thread가 된다. 그러므로, 17 Thread가 현재 System.Web.Compilation.BuildManager(08e05824)를 잡고 있는 Thread이므로 해당 Thread에서 exit 되지 않으며 다른 3개의 Thread에서의 처리를 요청한 User Hang을 느낄 수 있다.

 

0:017> !dso

OS Thread Id: 0xa5c (17)

ESP/REG  Object   Name

. . .

1a3cf2f0 08e05824 System.Web.Compilation.BuildManager

 

0:017> kb

ChildEBP RetAddr  Args to Child             

1a3ccd60 7c59a072 000001cc 00000000 00000000 NTDLL!ZwWaitForSingleObject+0xb

1a3ccd88 79e77fd1 000001cc ffffffff 00000000 KERNEL32!WaitForSingleObjectEx+0x71

1a3ccdcc 79e77f9a 000001cc ffffffff 00000000 mscorwks!PEImage::LoadImage+0x199

1a3cce1c 79e77f50 ffffffff 00000000 00000000 mscorwks!CLREvent::WaitEx+0x117

1a3cce2c 79f3b282 ffffffff 00000000 00000000 mscorwks!CLREvent::Wait+0x17

1a3cce3c 79f75d6a 00000000 f072ae20 00000000 mscorwks!SVR::GCHeap::WaitUntilGCComplete+0x32

1a3cce78 79e7ada1 f072aedc 00000000 1a3ccef8 mscorwks!Thread::RareDisablePreemptiveGC+0x1a1

1a3cceb0 79e7a6c9 79e7a6bd 0014a290 79e7a2c3 mscorwks!CrstBase::Enter+0x1e6

1a3cceb4 79e7a6bd 0014a290 79e7a2c3 7a38cf40 mscorwks!EEEnterCriticalSection+0x9

1a3ccebc 79e7a2c3 7a38cf40 0014a290 79eab324 mscorwks!CExecutionEngine::AcquireLock+0x9

1a3ccec8 79eab324 0014a290 002148f0 7a144ea3 mscorwks!ClrEnterCriticalSection+0xf

1a3cced4 7a144ea3 f072af58 00000000 002148f0 mscorwks!CCriticalSection::Lock+0x17

1a3cdb80 7a14560a 00000000 0000000a 00000000 mscorwks!CAssemblyCacheItem::MoveAssemblyToFinalLocation+0x31f

1a3cdbc8 7a143a97 0000000a 00000000 00000000 mscorwks!CAssemblyCacheItem::LegacyCommit+0x245

1a3cdc04 7a15e4b4 002148f0 00000000 00000000 mscorwks!CAssemblyCacheItem::Commit+0x5d

1a3ce2b0 7a15e936 1a3ce644 001f79c0 1a3ce328 mscorwks!CAsmDownloadMgr::CreateAssembly+0x85b

1a3ce2ec 7a15f074 1a3ce644 001f79c0 1a3ce328 mscorwks!CAsmDownloadMgr::DoSetupPushToCache+0x50

1a3ce574 79f8e8f8 001fc230 001f79c0 1a3ce644 mscorwks!CAsmDownloadMgr::DoSetup+0x26a

1a3ce5c0 79f8c05c 1a3ce644 00000000 f0728598 mscorwks!CAssemblyDownload::DoSetup+0x7b

1a3ce5f4 79f8bf74 00000000 1a3ce644 00000000 mscorwks!CAssemblyDownload::DownloadComplete+0xb6

 

상위에서는 PEImage Load 될 때까지는 Lock이 풀리지 않을 듯

by 강세윤 | 2009/07/10 17:33 | Windows debugging | 트랙백 | 덧글(0)
트랙백 주소 : http://byung.egloos.com/tb/5038154
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

< 이전페이지 다음페이지 >