결론부터 말씀드리자면... MS의 버그 되겠습니다. 

Windows7에서 발생하구요... MSDN에 따르면 SQL Server가 설치된 환경에서 잘 발생하는 모양입니다만, 반드시 그런것은 아닙니다. 제 PC에서도 발생했거든요. ^^;;


메모리 덤프를 잠시 살펴보면 다음과 같습니다.

0:014> !locks


CritSec ntdll!LdrpLoaderLock+0 at 778720c0

WaiterWoken        No

LockCount          0

RecursionCount     1

OwningThread       1a40

EntryCount         0

ContentionCount    7

*** Locked


CritSec ntdll!RtlpProcessHeapsListLock+0 at 77872120

WaiterWoken        No

LockCount          0

RecursionCount     2

OwningThread       22e0

EntryCount         0

ContentionCount    0

*** Locked


CritSec +530138 at 00530138

WaiterWoken        No

LockCount          1

RecursionCount     1

OwningThread       22e0

EntryCount         0

ContentionCount    5

*** Locked


CritSec +1e0138 at 001e0138

WaiterWoken        No

LockCount          1

RecursionCount     1

OwningThread       22e0

EntryCount         0

ContentionCount    1

*** Locked


CritSec +22c0138 at 022c0138

WaiterWoken        No

LockCount          0

RecursionCount     1

OwningThread       22e0

EntryCount         0

ContentionCount    0

*** Locked


CritSec +4d0138 at 004d0138

WaiterWoken        No

LockCount          1

RecursionCount     1

OwningThread       22e0

EntryCount         0

ContentionCount    1

*** Locked


CritSec +2850138 at 02850138

WaiterWoken        No

LockCount          1

RecursionCount     1

OwningThread       1a48

EntryCount         0

ContentionCount    2

*** Locked


CritSec +4d646c at 004d646c

WaiterWoken        No

LockCount          0

RecursionCount     1

OwningThread       22e0

EntryCount         0

ContentionCount    0

*** Locked


Scanned 480 critical sections


꽤 많은 크리티컬 섹션이 잠겨 있는데요... 두개를 제외하곤 모두 22e0 스레드가 점유하고 있네요.


이 스레드가 뭐하고 있나 한번 살펴볼까요??

0:014> ~~[22e0]s

eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=02850138 edi=00000000

eip=7778f8d1 esp=035cd104 ebp=035cd168 iopl=0         nv up ei pl zr na pe nc

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246

ntdll!ZwWaitForSingleObject+0x15:

7778f8d1 83c404          add     esp,4

0:005> kvn

 # ChildEBP RetAddr  Args to Child              

00 035cd104 777a8e44 0000028c 00000000 00000000 ntdll!ZwWaitForSingleObject+0x15 (FPO: [3,0,0])

01 035cd168 777a8d28 00000000 00000000 035cd318 ntdll!RtlpWaitOnCriticalSection+0x13e (FPO: [Non-Fpo])

02 035cd190 777a81b5 02850138 00000000 00000000 ntdll!RtlEnterCriticalSection+0x150 (FPO: [Non-Fpo])

03 035cd1c4 7782f7c5 02850000 747eba82 035cd358 ntdll!RtlLockHeap+0x3d (FPO: [Non-Fpo])

04 035cd2ac 777fdc16 035cd318 77813b65 00000000 ntdll!RtlpQueryExtendedHeapInformation+0xbd (FPO: [Non-Fpo])

05 035cd2ec 778141fd 00000000 00000002 035cd318 ntdll!RtlQueryHeapInformation+0x4a (FPO: [Non-Fpo])

06 035cd390 777f30dc 04570000 77240000 035cd494 ntdll!RtlQueryProcessHeapInformation+0x288 (FPO: [Non-Fpo])

07 035cd40c 772d5a0b 000006c8 00000014 04570000 ntdll!RtlQueryProcessDebugInformation+0x28a (FPO: [Non-Fpo])

08 035cd43c 0fa02364 04570000 b8a78c6f 00000014 kernel32!Heap32Next+0x4d (FPO: [Non-Fpo])

09 035cd950 0f9f1caf 00000000 0346fe18 035cd9e8 netclient!RAND_poll+0x574 (FPO: [Non-Fpo]) (CONV: cdecl) 

0a 035cd9a4 0f9f2060 00000010 00000001 0fa14a87 netclient!ssleay_rand_bytes+0xbf (FPO: [2,16,0]) (CONV: cdecl) 

0b 035cd9b0 0fa14a87 0346ff20 00000010 00000002 netclient!ssleay_rand_pseudo_bytes+0x10 (FPO: [2,0,0]) (CONV: cdecl) 

0c 035cd9d4 0f9490af 0fa9b530 034630a4 0fa9b530 netclient!SSL_CTX_new+0x297 (FPO: [1,0,4]) (CONV: cdecl) 

0d 035cd9e8 0f9474e4 00000001 b8a7a2e7 00000000 netclient!CSSL::Initialize+0x5f (FPO: [Non-Fpo]) (CONV: thiscall) 

// 이하 생략


0:005> !critsec 02850138 


CritSec +2850138 at 02850138

WaiterWoken        No

LockCount          1

RecursionCount     1

OwningThread       1a48

EntryCount         0

ContentionCount    2

*** Locked

0:005> ~~[1a48]s

eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=00530138 edi=00000000

eip=7778f8d1 esp=041eeea0 ebp=041eef04 iopl=0         nv up ei pl zr na pe nc

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246

ntdll!ZwWaitForSingleObject+0x15:

7778f8d1 83c404          add     esp,4

0:014> kvn

 # ChildEBP RetAddr  Args to Child              

00 041eeea0 777a8e44 00000288 00000000 00000000 ntdll!ZwWaitForSingleObject+0x15 (FPO: [3,0,0])

01 041eef04 777a8d28 00000000 00000000 00530000 ntdll!RtlpWaitOnCriticalSection+0x13e (FPO: [Non-Fpo])

02 041eef2c 777a8fa9 00530138 733c9826 00078000 ntdll!RtlEnterCriticalSection+0x150 (FPO: [Non-Fpo])

03 041ef008 777a3cfe 000003f8 00000400 00000000 ntdll!RtlpAllocateHeap+0x159 (FPO: [Non-Fpo])

04 041ef08c 777a7be3 00530000 00800000 000003f8 ntdll!RtlAllocateHeap+0x23a (FPO: [Non-Fpo])

05 041ef0d8 777a6e1b 00000028 733c9946 042f0048 ntdll!RtlpAllocateUserBlock+0xae (FPO: [Non-Fpo])

06 041ef168 7779e0f2 042f0048 042f0048 00000000 ntdll!RtlpLowFragHeapAllocFromContext+0x802 (FPO: [Non-Fpo])

07 041ef1dc 777a7ed9 00530000 00000000 00000020 ntdll!RtlAllocateHeap+0x206 (FPO: [Non-Fpo])

08 041ef1ec 777a4859 02850000 042f0048 00000000 ntdll!RtlpAllocateDebugInfo+0x28 (FPO: [0,0,0])

09 041ef228 777a2c9c 042f0048 00000000 00000000 ntdll!RtlInitializeCriticalSectionEx+0x93 (FPO: [Non-Fpo])

0a 041ef23c 777afe22 042f0048 042f0048 02850000 ntdll!RtlInitializeCriticalSection+0x12 (FPO: [Non-Fpo])

0b 041ef250 777afdf0 00000000 00000800 02850000 ntdll!RtlpInitializeLowFragHeap+0x28 (FPO: [Non-Fpo])

0c 041ef260 777afb9a 733c9ab6 028500cc 02850000 ntdll!RtlpCreateLowFragHeap+0x28 (FPO: [0,0,0])

0d 041ef298 777afc42 02850000 028503a4 041ef384 ntdll!RtlpActivateLowFragmentationHeap+0xc9 (FPO: [Non-Fpo])

0e 041ef2a8 777afc0e 02850000 733c9baa 720384c0 ntdll!RtlpPerformHeapMaintenance+0x2a (FPO: [Non-Fpo])

0f 041ef384 777a3cfe 00000214 00000220 028503a4 ntdll!RtlpAllocateHeap+0x172 (FPO: [Non-Fpo])

10 041ef408 720433ae 02850000 00000008 00000214 ntdll!RtlAllocateHeap+0x23a (FPO: [Non-Fpo])

11 041ef420 7203ede2 00000001 00000214 00000000 uFsCtl!_calloc_impl+0x49 (FPO: [Non-Fpo]) (CONV: cdecl) 

12 041ef43c 7203adf9 00000001 00000214 004dcaa0 uFsCtl!_calloc_crt+0x16 (FPO: [Non-Fpo]) (CONV: cdecl) 

13 041ef458 7203423d 00000000 00000000 720384c0 uFsCtl!_beginthreadex+0x36 (FPO: [Non-Fpo]) (CONV: cdecl) 

// 이하 생략


0:014> !critsec 00530138 


CritSec +530138 at 00530138

WaiterWoken        No

LockCount          1

RecursionCount     1

OwningThread       22e0

EntryCount         0

ContentionCount    5

*** Locked


음... 22e0 스레드는 CriticalSection 02850138를 얻기 위해 대기중이네요. 

그리고 02850138를 소유한 스레드는 CriticalSection 00530138를 얻기 위해 대기중인데... 이 00530138 란 놈을 소유한 스레드가 바로 22e0 되겠습니다... 전형적인 데드락이죠.


이상한 점은... 이 크리티컬섹션을 얻으려고 시도하는 모듈이 외부 모듈이 아니라 ntdll.dll 이라는 점입니다.

스레드 중 하나는 kernel32.dll 에서 Heap32Next api를 호출하여 내부적으로 크리티컬 섹션에 lock을 걸었고, 다른 스레드는 스레드가 생성되는 과정에서 RtlAllocateHeap을 호출했습니다. 말하자면, 그냥 win32 api를 호출했을 뿐인데 데드락이 발생한 것입니다. 

한마디로 Windows의 버그인 거죠.


찾아보니... HotFix가 나와있네요. (2012년 9월 17일에 발표된 HotFix입니다.)

http://support.microsoft.com/kb/2719306/en-us


기술문서 내용에 따르면 다음과 같이 되어 있습니다.


Collapse imageCause

This issue is caused by a dead lock situation that occurs when the Heap32First function and the RtlAllocateHeap function are called by two threads at the same time.


Heap32First와 RtlAllocateHeap 이 동시에 호출되면 데드락이 발생한다는 얘기네요.


또, 이런 말도 있습니다.

A supported hotfix is available from Microsoft. However, this hotfix is intended to correct only the problem that is described in this article. Apply this hotfix only to systems that are experiencing the problem described in this article. This hotfix might receive additional testing. Therefore, if you are not severely affected by this problem, we recommend that you wait for the next software update that contains this hotfix.


한마디로... 좀 더 테스트해봐야겠으니 급한 경우에만 써라 이거네요. ㅡ.ㅡ

저의 경우엔 클라이언트에서 발생하는 문제인데... 윈도우즈 업데이트에도 포함되지 않은 핫픽스 하나 내놓고 1년 가까이 배째라고 하면 어쩌란 건지... ㅡ.ㅡ


저의 경우엔 프로세스 시작 직후에 open_ssl 초기화와 스레드 생성이 동시에 발생하여 문제가 생겼습니다...

음... 

현재로서는... 스레드 생성과 open_ssl 초기화의 시점을 서로 분리하는 방안을 검토중입니다...


유사한 현상을 경험하신 분들께선 참고하시기 바랍니다. 







Posted by kuaaan
,


사랑합니다. 편안히 잠드소서