Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit ef24140

Browse files
committed
Add sos DumpAsync command
Debugging async methods with sos can be time consuming and relies on knowing how to use dumpheap, dumpvc, gcroot, and other commands to get the desired information, while often digging through a myriad of objects on the heap to find the desired info. This commit adds a new DumpAsync command, which finds the async state machine objects on the GC heap and outputs relevant information about each, including the fields of its state machine, any registered continuation, and GC roots for the state machine object (as they often serve as a valid substitute for call stacks). Example program used as a test: ```C# using System.Threading.Tasks; class Program { static async Task Main() => await MethodA(); static async Task MethodA() => await MethodB(); static async Task MethodB() => await MethodC(); static async Task MethodC() => await MethodD(); static async Task MethodD() => await Task.Delay(int.MaxValue); } ``` and example command output: ``` 0:011> !DumpAsync -type MethodD Address MT Size Name 000001989f413de0 00007ff88c506ba8 112 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]] StateMachine: Program+<MethodD>d__4 MT Field Offset Type VT Attr Value Name 00007ff8d3df4b80 400000d 0 System.Int32 1 instance 0 <>1__state 00007ff8d3e082c0 400000e 8 ...TaskMethodBuilder 1 instance 000001989f413e38 <>t__builder 00007ff8d3dfea90 400000f 10 ...vices.TaskAwaiter 1 instance 000001989f413e40 <>u__1 Continuation: 000001989f413e50 (System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]]) GC roots: Thread 2936c: 000000071a37e050 00007ff8d3ac1657 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [d:\repos\coreclr\src\System.Private.CoreLib\src\System\Threading\Tasks\Task.cs @ 2977] rbp+10: 000000071a37e0c0 -> 000001989f413fa0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<Main>d__0, test]] -> 000001989f413f30 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodA>d__1, test]] -> 000001989f413ec0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodB>d__2, test]] -> 000001989f413e50 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]] -> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]] HandleTable: 000001989d8415f8 (pinned handle) -> 00000198af3e1038 System.Object[] -> 000001989f413410 System.Threading.TimerQueue[] -> 000001989f413468 System.Threading.TimerQueue -> 000001989f413330 System.Threading.TimerQueueTimer -> 000001989f412e40 System.Threading.Tasks.Task+DelayPromise -> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]] Found 1 state machines. ```
1 parent 59f07a0 commit ef24140

File tree

9 files changed

+357
-29
lines changed

9 files changed

+357
-29
lines changed

src/ToolBox/SOS/Strike/apollososdocs.txt

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ Object Inspection Examining code and stacks
2525
----------------------------- -----------------------------
2626
DumpObj (do) Threads
2727
DumpArray (da) ThreadState
28-
DumpStackObjects (dso) IP2MD
29-
DumpHeap U
30-
DumpVC DumpStack
31-
GCRoot EEStack
32-
ObjSize CLRStack
33-
FinalizeQueue GCInfo
34-
PrintException (pe) EHInfo
35-
TraverseHeap BPMD
36-
Watch COMState
37-
StopOnCatch
28+
DumpAsync IP2MD
29+
DumpStackObjects (dso) U
30+
DumpHeap DumpStack
31+
DumpVC EEStack
32+
GCRoot CLRStack
33+
ObjSize GCInfo
34+
FinalizeQueue EHInfo
35+
PrintException (pe) BPMD
36+
TraverseHeap COMState
37+
Watch StopOnCatch
3838
SuppressJitOptimization
3939

4040
Examining CLR data structures Diagnostic Utilities
@@ -340,6 +340,62 @@ The arguments in detail:
340340
5b9a628c 4000002 4 System.Int32 instance 8 y
341341
5b9a628c 4000003 8 System.Int32 instance 12 z
342342

343+
\\
344+
345+
COMMAND: dumpasync.
346+
!DumpAsync [-mt <MethodTable address>]
347+
[-type <partial type name>]]
348+
349+
!DumpAsync traverses the garbage collected heap, looking for objects representing
350+
async state machines as created when an async method's state is transferred to the
351+
heap. This command recognizes async state machines defined as "async void", "async Task",
352+
"async Task<T>", "async ValueTask", and "async ValueTask<T>".
353+
354+
The output includes a block of details for each async state machine object found.
355+
These details include:
356+
- a line for the type of the async state machine object, including its MethodTable address,
357+
its object address, its size, and its type name.
358+
- a line for the state machine type name as contained in the object.
359+
- a listing of each field on the state machine.
360+
- a line for a continuation from this state machine object, if one or more has been registered.
361+
- discovered GC roots for this async state machine object.
362+
363+
For example:
364+
365+
0:011> !DumpAsync
366+
#0
367+
000001989f413de0 00007ff88c506ba8 112 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
368+
StateMachine: Program+<MethodD>d__4
369+
MT Field Offset Type VT Attr Value Name
370+
00007ff8d3df4b80 400000d 0 System.Int32 1 instance 0 <>1__state
371+
00007ff8d3e082c0 400000e 8 ...TaskMethodBuilder 1 instance 000001989f413e38 <>t__builder
372+
00007ff8d3dfea90 400000f 10 ...vices.TaskAwaiter 1 instance 000001989f413e40 <>u__1
373+
Continuation: 000001989f413e50 (System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]])
374+
GC roots:
375+
Thread 2936c:
376+
000000071a37e050 00007ff8d3ac1657 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [d:\repos\coreclr\src\System.Private.CoreLib\src\System\Threading\Tasks\Task.cs @ 2977]
377+
rbp+10: 000000071a37e0c0
378+
-> 000001989f413fa0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<Main>d__0, test]]
379+
-> 000001989f413f30 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodA>d__1, test]]
380+
-> 000001989f413ec0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodB>d__2, test]]
381+
-> 000001989f413e50 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]]
382+
-> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
383+
HandleTable:
384+
000001989d8415f8 (pinned handle)
385+
-> 00000198af3e1038 System.Object[]
386+
-> 000001989f413410 System.Threading.TimerQueue[]
387+
-> 000001989f413468 System.Threading.TimerQueue
388+
-> 000001989f413330 System.Threading.TimerQueueTimer
389+
-> 000001989f412e40 System.Threading.Tasks.Task+DelayPromise
390+
-> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
391+
...
392+
393+
394+
The arguments in detail:
395+
396+
-mt List only those objects with the MethodTable given.
397+
-type List only those objects whose type name is a substring match of the
398+
string provided.
343399

344400
\\
345401

src/ToolBox/SOS/Strike/sos.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ EXPORTS
1515
dumparray=DumpArray
1616
DumpAssembly
1717
dumpassembly=DumpAssembly
18+
DumpAsync
19+
dumpasync=DumpAsync
1820
DumpClass
1921
dumpclass=DumpClass
2022
DumpDomain

src/ToolBox/SOS/Strike/sos_unixexports.src

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ ClrStack
77
CreateDump
88
DumpArray
99
DumpAssembly
10+
DumpAsync
1011
DumpClass
1112
DumpDomain
1213
DumpGCData

src/ToolBox/SOS/Strike/sosdocs.txt

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ Object Inspection Examining code and stacks
2525
----------------------------- -----------------------------
2626
DumpObj (do) Threads
2727
DumpArray (da) ThreadState
28-
DumpStackObjects (dso) IP2MD
29-
DumpHeap U
30-
DumpVC DumpStack
31-
GCRoot EEStack
32-
ObjSize CLRStack
33-
FinalizeQueue GCInfo
34-
PrintException (pe) EHInfo
35-
TraverseHeap BPMD
36-
COMState
28+
DumpAsync IP2MD
29+
DumpStackObjects (dso) U
30+
DumpHeap DumpStack
31+
DumpVC EEStack
32+
GCRoot CLRStack
33+
ObjSize GCInfo
34+
FinalizeQueue EHInfo
35+
PrintException (pe) BPMD
36+
TraverseHeap COMState
3737

3838
Examining CLR data structures Diagnostic Utilities
3939
----------------------------- -----------------------------
@@ -338,6 +338,62 @@ The arguments in detail:
338338
5b9a628c 4000002 4 System.Int32 instance 8 y
339339
5b9a628c 4000003 8 System.Int32 instance 12 z
340340

341+
\\
342+
343+
COMMAND: dumpasync.
344+
!DumpAsync [-mt <MethodTable address>]
345+
[-type <partial type name>]]
346+
347+
!DumpAsync traverses the garbage collected heap, looking for objects representing
348+
async state machines as created when an async method's state is transferred to the
349+
heap. This command recognizes async state machines defined as "async void", "async Task",
350+
"async Task<T>", "async ValueTask", and "async ValueTask<T>".
351+
352+
The output includes a block of details for each async state machine object found.
353+
These details include:
354+
- a line for the type of the async state machine object, including its MethodTable address,
355+
its object address, its size, and its type name.
356+
- a line for the state machine type name as contained in the object.
357+
- a listing of each field on the state machine.
358+
- a line for a continuation from this state machine object, if one or more has been registered.
359+
- discovered GC roots for this async state machine object.
360+
361+
For example:
362+
363+
0:011> !DumpAsync
364+
#0
365+
000001989f413de0 00007ff88c506ba8 112 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
366+
StateMachine: Program+<MethodD>d__4
367+
MT Field Offset Type VT Attr Value Name
368+
00007ff8d3df4b80 400000d 0 System.Int32 1 instance 0 <>1__state
369+
00007ff8d3e082c0 400000e 8 ...TaskMethodBuilder 1 instance 000001989f413e38 <>t__builder
370+
00007ff8d3dfea90 400000f 10 ...vices.TaskAwaiter 1 instance 000001989f413e40 <>u__1
371+
Continuation: 000001989f413e50 (System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]])
372+
GC roots:
373+
Thread 2936c:
374+
000000071a37e050 00007ff8d3ac1657 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [d:\repos\coreclr\src\System.Private.CoreLib\src\System\Threading\Tasks\Task.cs @ 2977]
375+
rbp+10: 000000071a37e0c0
376+
-> 000001989f413fa0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<Main>d__0, test]]
377+
-> 000001989f413f30 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodA>d__1, test]]
378+
-> 000001989f413ec0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodB>d__2, test]]
379+
-> 000001989f413e50 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]]
380+
-> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
381+
HandleTable:
382+
000001989d8415f8 (pinned handle)
383+
-> 00000198af3e1038 System.Object[]
384+
-> 000001989f413410 System.Threading.TimerQueue[]
385+
-> 000001989f413468 System.Threading.TimerQueue
386+
-> 000001989f413330 System.Threading.TimerQueueTimer
387+
-> 000001989f412e40 System.Threading.Tasks.Task+DelayPromise
388+
-> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
389+
...
390+
391+
392+
The arguments in detail:
393+
394+
-mt List only those objects with the MethodTable given.
395+
-type List only those objects whose type name is a substring match of the
396+
string provided.
341397

342398
\\
343399

src/ToolBox/SOS/Strike/sosdocsunix.txt

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ Object Inspection Examining code and stacks
2525
----------------------------- -----------------------------
2626
DumpObj (dumpobj) Threads (clrthreads)
2727
DumpArray ThreadState
28-
DumpStackObjects (dso) IP2MD (ip2md)
29-
DumpHeap (dumpheap) u (clru)
30-
DumpVC DumpStack (dumpstack)
31-
GCRoot (gcroot) EEStack (eestack)
32-
PrintException (pe) ClrStack (clrstack)
33-
GCInfo
28+
DumpAsync IP2MD (ip2md)
29+
DumpStackObjects (dso) u (clru)
30+
DumpHeap (dumpheap) DumpStack (dumpstack)
31+
DumpVC EEStack (eestack)
32+
GCRoot (gcroot) CLRStack (clrstack)
33+
PrintException (pe) GCInfo
3434
EHInfo
3535
bpmd (bpmd)
3636

@@ -199,6 +199,62 @@ The arguments in detail:
199199
5b9a628c 4000002 4 System.Int32 instance 8 y
200200
5b9a628c 4000003 8 System.Int32 instance 12 z
201201

202+
\\
203+
204+
COMMAND: dumpasync.
205+
!DumpAsync [-mt <MethodTable address>]
206+
[-type <partial type name>]]
207+
208+
!DumpAsync traverses the garbage collected heap, looking for objects representing
209+
async state machines as created when an async method's state is transferred to the
210+
heap. This command recognizes async state machines defined as "async void", "async Task",
211+
"async Task<T>", "async ValueTask", and "async ValueTask<T>".
212+
213+
The output includes a block of details for each async state machine object found.
214+
These details include:
215+
- a line for the type of the async state machine object, including its MethodTable address,
216+
its object address, its size, and its type name.
217+
- a line for the state machine type name as contained in the object.
218+
- a listing of each field on the state machine.
219+
- a line for a continuation from this state machine object, if one or more has been registered.
220+
- discovered GC roots for this async state machine object.
221+
222+
For example:
223+
224+
(lldb) dumpasync
225+
#0
226+
000001989f413de0 00007ff88c506ba8 112 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
227+
StateMachine: Program+<MethodD>d__4
228+
MT Field Offset Type VT Attr Value Name
229+
00007ff8d3df4b80 400000d 0 System.Int32 1 instance 0 <>1__state
230+
00007ff8d3e082c0 400000e 8 ...TaskMethodBuilder 1 instance 000001989f413e38 <>t__builder
231+
00007ff8d3dfea90 400000f 10 ...vices.TaskAwaiter 1 instance 000001989f413e40 <>u__1
232+
Continuation: 000001989f413e50 (System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]])
233+
GC roots:
234+
Thread 2936c:
235+
000000071a37e050 00007ff8d3ac1657 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [d:\repos\coreclr\src\System.Private.CoreLib\src\System\Threading\Tasks\Task.cs @ 2977]
236+
rbp+10: 000000071a37e0c0
237+
-> 000001989f413fa0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<Main>d__0, test]]
238+
-> 000001989f413f30 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodA>d__1, test]]
239+
-> 000001989f413ec0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodB>d__2, test]]
240+
-> 000001989f413e50 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodC>d__3, test]]
241+
-> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
242+
HandleTable:
243+
000001989d8415f8 (pinned handle)
244+
-> 00000198af3e1038 System.Object[]
245+
-> 000001989f413410 System.Threading.TimerQueue[]
246+
-> 000001989f413468 System.Threading.TimerQueue
247+
-> 000001989f413330 System.Threading.TimerQueueTimer
248+
-> 000001989f412e40 System.Threading.Tasks.Task+DelayPromise
249+
-> 000001989f413de0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Program+<MethodD>d__4, test]]
250+
...
251+
252+
253+
The arguments in detail:
254+
255+
-mt List only those objects with the MethodTable given.
256+
-type List only those objects whose type name is a substring match of the
257+
string provided.
202258

203259
\\
204260

0 commit comments

Comments
 (0)