Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 65 additions & 13 deletions src/SosThreadingTools/DumpAsyncCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ private static void GetAllStateMachines(ClrHeap heap, List<AsyncStateMachine> al
}
}
}

ClrObject currentObject = stateMachine.TryGetObjectField("<>4__this");
if (!currentObject.IsNull && currentObject.Type is not null && string.Equals(currentObject.Type.Name, "Microsoft.VisualStudio.Threading.JoinableTaskCollection", StringComparison.Ordinal))
{
asyncState.WaitingJoinableTasks = GetJoinableTasksFromCollection(currentObject);
}
}
}
#pragma warning disable CA1031 // Do not catch general exception types
Expand All @@ -183,6 +189,40 @@ private static void GetAllStateMachines(ClrHeap heap, List<AsyncStateMachine> al
}
}

private static List<ClrObject> GetJoinableTasksFromCollection(ClrObject joinableTaskCollection)
{
var joinableTasks = new List<ClrObject>();
ClrValueType? dependentData = joinableTaskCollection.TryGetValueClassField("dependentData");
if (dependentData is not null)
{
ClrObject childDependentNodes = dependentData.TryGetObjectField("childDependentNodes");
if (!childDependentNodes.IsNull &&
childDependentNodes.TryReadField<int>("count", out int count) &&
childDependentNodes.TryReadField<int>("freeCount", out int freeCount))
{
count -= freeCount;
if (count > 0)
{
ClrObject entries = childDependentNodes.TryGetObjectField("entries");
if (!entries.IsNull && entries.IsArray && entries.AsArray() is ClrArray entriesArray)
{
for (int i = 0; i < entriesArray.Length; i++)
{
ClrValueType? value = entriesArray.GetStructValue(i);
ClrObject key = value.TryGetObjectField("key");
if (!key.IsNull)
{
joinableTasks.Add(key);
}
}
Comment thread
lifengl marked this conversation as resolved.
}
}
}
}

return joinableTasks;
}

private static void ChainStateMachinesBasedOnTaskContinuations(Dictionary<ulong, AsyncStateMachine> knownStateMachines)
{
foreach (AsyncStateMachine? stateMachine in knownStateMachines.Values)
Expand Down Expand Up @@ -285,16 +325,13 @@ private static void ChainStateMachinesBasedOnJointableTasks(List<AsyncStateMachi
try
{
ClrObject joinableTask = stateMachine.StateMachine.TryGetObjectField("<>4__this");
ClrObject wrappedTask = joinableTask.TryGetObjectField("wrappedTask");
if (!wrappedTask.IsNull)
FindWaitingTaskFromJoinableTask(joinableTask, stateMachine);

if (stateMachine.WaitingJoinableTasks is List<ClrObject> joinableTasks)
{
AsyncStateMachine? previousStateMachine = allStateMachines
.FirstOrDefault(s => s.Task.Address == wrappedTask.Address);
if (previousStateMachine is object && stateMachine != previousStateMachine)
foreach (ClrObject waitingJoinableTask in joinableTasks)
{
stateMachine.Previous = previousStateMachine;
previousStateMachine.Next = stateMachine;
previousStateMachine.DependentCount++;
FindWaitingTaskFromJoinableTask(waitingJoinableTask, stateMachine);
}
}
}
Expand All @@ -306,6 +343,22 @@ private static void ChainStateMachinesBasedOnJointableTasks(List<AsyncStateMachi
}
}
}

void FindWaitingTaskFromJoinableTask(ClrObject joinableTask, AsyncStateMachine currentStateMachine)
{
ClrObject wrappedTask = joinableTask.TryGetObjectField("wrappedTask");
if (!wrappedTask.IsNull)
{
AsyncStateMachine? previousStateMachine = allStateMachines
.FirstOrDefault(s => s.Task.Address == wrappedTask.Address);
if (previousStateMachine is object && currentStateMachine != previousStateMachine)
{
currentStateMachine.Previous ??= previousStateMachine;
previousStateMachine.Next = currentStateMachine;
Comment thread
lifengl marked this conversation as resolved.
Outdated
previousStateMachine.DependentCount++;
}
}
}
}

private static void MarkUIThreadDependingTasks(List<AsyncStateMachine> allStateMachines)
Expand Down Expand Up @@ -388,7 +441,7 @@ private void MarkThreadingBlockTasks(ClrHeap heap, List<AsyncStateMachine> allSt
}
}

break;
continue;
}
}
}
Expand Down Expand Up @@ -438,10 +491,7 @@ private void PrintOutStateMachines(List<AsyncStateMachine> allStateMachines)
{
bool multipleLineBlock = this.PrintAsyncStateMachineChain(node, printedMachines);
Comment thread
lifengl marked this conversation as resolved.
Outdated

if (multipleLineBlock)
{
Console.WriteLine(string.Empty);
}
Console.WriteLine(string.Empty);
}

// Print nodes which we didn't print because of loops.
Expand Down Expand Up @@ -573,6 +623,8 @@ public AsyncStateMachine(int state, ClrObject stateMachine, ClrObject task)

public AsyncStateMachine? AlterPrevious { get; set; }

public List<ClrObject>? WaitingJoinableTasks { get; set; }

public ulong CodeAddress { get; set; }

public override string ToString()
Expand Down
Loading