Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

(시리즈 글이 3개 있습니다.)
디버깅 기술: 93. windbg - 풀 덤프에서 .NET 스레드의 상태를 알아내는 방법
; https://www.sysnet.pe.kr/2/0/11269

디버깅 기술: 114. windbg - !threads 출력 결과로부터 닷넷 관리 스레드(System.Threading.Thread) 객체를 구하는 방법
; https://www.sysnet.pe.kr/2/0/11476

.NET Framework: 790. .NET Thread 상태가 Cooperative일 때 GC hang 현상 재현 방법
; https://www.sysnet.pe.kr/2/0/11634




windbg - !threads 출력 결과로부터 닷넷 관리 스레드(System.Threading.Thread) 객체를 구하는 방법

모든 스레드를 열거하는 가장 쉬운 방법으로 !threads 명령어가 있습니다.

0:017> !threads
ThreadCount: 298
UnstartedThread: 0
BackgroundThread: 298
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
  26    1  fd4 00117830   1808220 Enabled  406dc694:406dc6b8 07c6bf90     1 MTA (Threadpool Worker)
  44    2  dd8 001345c8      b220 Enabled  00000000:00000000 000de1d8     0 MTA (Finalizer)
  45    3  db8 03f8fc18    80a220 Enabled  00000000:00000000 000de1d8     0 MTA (Threadpool Completion Port)
  46    4  ddc 03fe6c78      1220 Enabled  00000000:00000000 000de1d8     0 Ukn
  47    5  de8 05450cd0      b220 Enabled  4ff022a0:4ff022b0 03fe7258     0 MTA
  48    6  dc8 058a38e0   200b220 Enabled  4fe61b04:4fe620d8 03fe7258     0 MTA
  49    7  a9c 07592be8   200b220 Enabled  3c477948:3c478044 03fe7258     0 MTA
  50    8  dbc 075935d8      b220 Enabled  4412dd90:4412dd90 03fe7258     0 MTA
  51    9  5b8 07592308   200b220 Enabled  00000000:00000000 03fe7258     0 MTA
  52    a 16c8 07625850    80a220 Enabled  00000000:00000000 000de1d8     0 MTA (Threadpool Completion Port)
  24    b 1794 07626358   180a220 Enabled  00000000:00000000 000de1d8     0 MTA (Threadpool Worker)
  53    c 1738 0762dfe0      b220 Enabled  1616926c:16169274 03fe7258     0 MTA
  54    d 1678 0766cc40   200b220 Enabled  00000000:00000000 03fe7258     0 MTA
  55    e 10e4 0766bd10   200b220 Enabled  00000000:00000000 03fe7258     0 MTA
  56    f   6c 0766dd68   200b220 Enabled  00000000:00000000 03fe7258     0 MTA
  57   10 1330 0766f550   180b220 Enabled  4ef9a2c0:4ef9a2c4 07c6bf90     1 MTA (Threadpool Worker)
  58   11  208 07670718   188b224 Enabled  43445c70:43445d60 07f41fc8     1 MTA (Threadpool Worker)
...[생략]...

그런데 이 정보들로부터 System.Threading.Thread 타입을 구할 수 있는 방법이 없습니다. (혹시 쉽게 구하는 방법을 아시는 분은 덧글 부탁드립니다. ^^)

물론 다소 불편하지만 우회 방법은 있습니다. 관리 힙을 전부 뒤져서 System.Threading.Thread 타입인 것을 찾는 것인데 시작은 우선 -mt에 해당하는 MethodTable 값을 찾아야 합니다. 이에 대해서는 전에도 설명했었는데,

windbg - 닷넷 메모리 덤프에서 전역 객체의 내용을 조사하는 방법
; https://www.sysnet.pe.kr/2/0/11460

위의 내용에 따라, 다음의 명령어로 가능합니다.

0:017> !name2ee mscorlib!System.Threading.Thread
Module: 02d32010 (mscorlib.dll)
Token: 0x02000154
MethodTable: 043117dc
EEClass: 02db3280
Name: System.Threading.Thread

이렇게 구한 MethodTable == 0x43117dc를 dumpheap 명령어에 전달하면, 관리 힙에 할당되어 있는 System.Threading.Thread 타입의 인스턴스를 모두 열람해 줍니다.

0:017> !DumpHeap -mt  043117dc
------------------------------
Heap 0
 Address       MT     Size
100b1c24 043117dc       56     
1019450c 043117dc       56     
101ad1b4 043117dc       56     
101ad5b4 043117dc       56     
101ad804 043117dc       56     
101ada00 043117dc       56     
10271920 043117dc       56     
10283be8 043117dc       56     
10283f3c 043117dc       56     
10284180 043117dc       56     
10284494 043117dc       56     
103334f8 043117dc       56     
10354f28 043117dc       56     
10441584 043117dc       56     
10451968 043117dc       56     
1053a824 043117dc       56     
105c7fe4 043117dc       56     
106139b0 043117dc       56     
10613d04 043117dc       56     
10613f48 043117dc       56     
1061425c 043117dc       56   
...[생략]...

출력 결과에 나온 각각의 Address 값을 덤프해 보면,

0:017> !do 100b1c24 
Name: System.Threading.Thread
MethodTable: 043117dc
EEClass: 02db3280
Size: 56(0x38) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
05d011f4  4000640        4 ....Contexts.Context  0 instance 141c6858 m_Context
05d0fb08  4000641        8 ....ExecutionContext  0 instance 31df6ee0 m_ExecutionContext
02d3914c  4000642        c        System.String  0 instance 00000000 m_Name
04310bb4  4000643       10      System.Delegate  0 instance 00000000 m_Delegate
05f0e400  4000644       14    System.Object[][]  0 instance 1084adc0 m_ThreadStaticsBuckets
0493cc30  4000645       18       System.Int32[]  0 instance 1084addc m_ThreadStaticsBits
0431677c  4000646       1c ...ation.CultureInfo  0 instance 00000000 m_CurrentCulture
0431677c  4000647       20 ...ation.CultureInfo  0 instance 00000000 m_CurrentUICulture
02d36d5c  4000648       24        System.Object  0 instance 00000000 m_ThreadStartArg
0431698c  4000649       28        System.IntPtr  1 instance   117830 DONT_USE_InternalThread
043c9a54  400064a       2c         System.Int32  1 instance        2 m_Priority
043c9a54  400064b       30         System.Int32  1 instance        1 m_ManagedThreadId
0493e488  400064c      16c ...LocalDataStoreMgr  0   shared   static s_LocalDataStoreMgr
    >> Domain:Value  000de1d8:00000000 03fe7258:1a0b1d2c 0778f8c0:00000000 07c6bf90:00000000 07e6d3d0:00000000 07eb6318:00000000 07f41fc8:00000000 080977e0:00000000 0812b6f0:00000000 0814feb8:00000000 082a2228:1d154ca0 083bea88:00000000 2c9ba550:00000000 0835c508:00000000 2cc681a0:00000000 2d157008:00000000 2d84be60:00000000 2d8b07b8:00000000 2d9d1c10:00000000 2da783e0:00000000 2daf2008:00000000 2db19ff0:00000000 08359a40:00000000 2dc1eea8:1476a408 2dd59f48:00000000 2ddfa9b0:00000000 2cc617e8:00000000 2df14d18:00000000 <<
02d36d5c  400064d      170        System.Object  0   shared   static s_SyncObject
    >> Domain:Value  000de1d8:100b1c18 03fe7258:100b5334 0778f8c0:140b2f24 07c6bf90:141c91c4 07e6d3d0:190b422c 07eb6318:142ec160 07f41fc8:143e1aec 080977e0:101b45b4 0812b6f0:1028a610 0814feb8:1e0b4510 082a2228:10377148 083bea88:1c0e63b8 2c9ba550:1047b448 0835c508:10552bcc 2cc681a0:18116530 2d157008:14380520 2d84be60:18219410 2d8b07b8:1069b6f8 2d9d1c10:182f6058 2da783e0:107c3890 2daf2008:12109898 2db19ff0:10625e0c 08359a40:1713b278 2dc1eea8:1c24aa14 2dd59f48:1a19071c 2ddfa9b0:1d1c87ac 2cc617e8:1f1b7e34 2df14d18:1d2e5a0c <<

DONT_USE_InternalThread 값이 !threads 목록에 있는 것과 같다는 것을 알 수 있습니다.

그런데... 스레드가 한두 개라면 모를까, 일반적인 프로그램에서 그 많은 스레드의 객체를 일일이 저렇게 뒤져보는 것도 일입니다. 따라서 이런 경우에는 pykd의 도움을 받아 스크립트로 만들어 두면 됩니다. 관련 스크립트의 힌트는 다음에서 이미 설명했었습니다.

windbg - 풀 덤프에서 .NET 스레드의 상태를 알아내는 방법
; https://www.sysnet.pe.kr/2/0/11269

따라서 이 글에 저 스크립트를 적용하면 다음과 같이 모든 Thread 타입의 관련 값을 열거할 수 있습니다.

0:006> .foreach ($t {!dumpheap -mt 043117dc -short}) {  .printf " Thread Obj ${$t} and the Thread Id is %N \n",poi(${$t}+4c) }

또는 pykd를 이용하면 좀 더 구체적으로 결과를 뽑아낼 수 있습니다.

windbg에서 python 스크립트 실행하는 방법 - pykd
; https://www.sysnet.pe.kr/2/0/11227

즉, 다음과 같이 thread ID를 기준으로 System.Threading.Thread 객체를 구할 수 있습니다.

from pykd import *

findId = "7670718"

def getItem(text, key):
    for line in text.splitlines():
        if key in line:
            result = line.split(":")[1].strip()
    return result

def GetManagedId(text):
    for line in text.splitlines():
        items = line.split()
        if len(items) >= 7 and items[7] == "DONT_USE_InternalThread":
            return items[6]

    return "NOT FOUND"

outputText = pykd.dbgCommand("!name2ee mscorlib!System.Threading.Thread")

mtThread = getItem(outputText, "MethodTable:")

outputText = pykd.dbgCommand("!DumpHeap -mt " + mtThread)

for line in outputText.splitlines():
    items = line.split()
    if len(items) == 3:
        threadAddress = items[0].strip()
        threadText = pykd.dbgCommand("!do " + threadAddress)

        managedId = GetManagedId(threadText)

        if managedId != "NOT FOUND":
            if managedId == findId:
                dprintln(threadText)
                break

dprintln ("END")

그런데... 시간이 좀 오래 걸린다는 흠이 있긴 합니다. ^^ 참고로, 위의 명령어를 응용하면 Managed Thread Id 값을 알고 있는 상태에서 그것의 System.Threading.Thread 인스턴스를 구하는 것도 가능합니다.

from pykd import *

findId = "17"

def getItem(text, key):
    for line in text.splitlines():
        if key in line:
            result = line.split(":")[1].strip()
    return result

def GetManagedId(text):
    for line in text.splitlines():
        items = line.split()
        if len(items) >= 7 and items[7] == "m_ManagedThreadId":
            return items[6]

    return "NOT FOUND"

outputText = pykd.dbgCommand("!name2ee mscorlib!System.Threading.Thread")

mtThread = getItem(outputText, "MethodTable:")

outputText = pykd.dbgCommand("!DumpHeap -mt " + mtThread)

for line in outputText.splitlines():
    items = line.split()
    if len(items) == 3:
        threadAddress = items[0].strip()
        threadText = pykd.dbgCommand("!do " + threadAddress)

        managedId = GetManagedId(threadText)

        if managedId != "NOT FOUND":
            if managedId == findId:
                dprintln(threadText)
                break

dprintln ("END")




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 4/9/2018]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




1  2  3  4  5  [6]  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13672정성태7/10/20243151닷넷: 2274. IIS - (프로세스 종료 없는) AppDomain Recycle
13671정성태7/10/20242995오류 유형: 914. Package ca-certificates is not installed.
13669정성태7/9/20243148오류 유형: 913. C# - AOT StaticExecutable 정적 링킹 시 빌드 오류
13668정성태7/8/20243067개발 환경 구성: 716. Hyper-V - Ubuntu 22.04 Generation 2 유형의 VM 설치
13667정성태7/7/20242670닷넷: 2273. C# - 리눅스 환경에서의 Hyper-V Socket 연동 (AF_VSOCK)파일 다운로드1
13666정성태7/7/20243344Linux: 74. C++ - Vsock 예제 (Hyper-V Socket 연동)파일 다운로드1
13665정성태7/6/20243369Linux: 73. Linux 측의 socat을 이용한 Hyper-V 호스트와의 vsock 테스트파일 다운로드1
13663정성태7/5/20243149닷넷: 2272. C# - Hyper-V Socket 통신(AF_HYPERV, AF_VSOCK)의 VMID Wildcards 유형파일 다운로드1
13662정성태7/4/20243555닷넷: 2271. C# - WSL 2 VM의 VM ID를 알아내는 방법 - Host Compute System API파일 다운로드1
13661정성태7/3/20243378Linux: 72. g++ - 다른 버전의 GLIBC로 소스코드 빌드
13660정성태7/3/20243233오류 유형: 912. Visual C++ - Linux 프로젝트 빌드 오류
13659정성태7/1/20243584개발 환경 구성: 715. Windows - WSL 2 환경의 Docker Desktop 네트워크
13658정성태6/28/20243534개발 환경 구성: 714. WSL 2 인스턴스와 호스트 측의 Hyper-V에 운영 중인 VM과 네트워크 연결을 하는 방법 - 두 번째 이야기
13657정성태6/27/20243761닷넷: 2270. C# - Hyper-V Socket 통신(AF_HYPERV, AF_VSOCK)을 위한 EndPoint 사용자 정의
13656정성태6/27/20243373Windows: 264. WSL 2 VM의 swap 파일 위치
13655정성태6/24/20243408닷넷: 2269. C# - Win32 Resource 포맷 해석파일 다운로드1
13654정성태6/24/20243393오류 유형: 911. shutdown - The entered computer name is not valid or remote shutdown is not supported on the target computer.
13653정성태6/22/20243447닷넷: 2268. C# 코드에서 MAKEINTREOURCE 매크로 처리
13652정성태6/21/20244035닷넷: 2267. C# - Linux 환경에서 (Reflection 없이) DLL AssemblyFileVersion 구하는 방법파일 다운로드2
13651정성태6/19/20243603닷넷: 2266. C# - (Reflection 없이) DLL AssemblyFileVersion 구하는 방법파일 다운로드1
13650정성태6/18/20243626개발 환경 구성: 713. "WSL --debug-shell"로 살펴보는 WSL 2 VM의 리눅스 환경
13649정성태6/18/20243196오류 유형: 910. windbg - !py 확장 명령어 실행 시 "failed to find python interpreter" (2)
13648정성태6/17/20243212오류 유형: 909. C# - DynamicMethod 사용 시 System.TypeAccessException
13647정성태6/16/20243802개발 환경 구성: 712. Windows - WSL 2의 네트워크 통신 방법 - 세 번째 이야기 (같은 IP를 공유하는 WSL 2 인스턴스) [1]
13646정성태6/14/20243064오류 유형: 908. Process Explorer - "Error configuring dump resources: The system cannot find the file specified."
13645정성태6/13/20243658개발 환경 구성: 711. Visual Studio로 개발 시 기본 등록하는 dev tag 이미지로 Docker Desktop k8s에서 실행하는 방법
1  2  3  4  5  [6]  7  8  9  10  11  12  13  14  15  ...