in src/SosThreadingTools/DumpAsyncCommand.cs [205:264]
private static void ChainStateMachineBasedOnTaskContinuations(Dictionary<ulong, AsyncStateMachine> knownStateMachines, AsyncStateMachine stateMachine, ClrObject continuationObject)
{
ClrObject continuationAction = continuationObject.TryGetObjectField("m_action");
// case 1
ClrObject continuationTarget = continuationAction.TryGetObjectField("_target");
if (continuationTarget.IsNull)
{
// case 2
continuationTarget = continuationObject.TryGetObjectField("_target");
if (continuationTarget.IsNull)
{
// case 3
continuationTarget = continuationObject.TryGetObjectField("m_task").TryGetObjectField("m_stateObject").TryGetObjectField("_target");
}
}
while (!continuationTarget.IsNull)
{
// now get the continuation from the target
ClrObject continuationTargetStateMachine = continuationTarget.TryGetObjectField("m_stateMachine");
if (!continuationTargetStateMachine.IsNull)
{
AsyncStateMachine targetAsyncState;
if (knownStateMachines.TryGetValue(continuationTargetStateMachine.Address, out targetAsyncState) && targetAsyncState != stateMachine)
{
stateMachine.Next = targetAsyncState;
stateMachine.DependentCount++;
targetAsyncState.Previous = stateMachine;
}
break;
}
else
{
ClrObject nextContinuation = continuationTarget.TryGetObjectField("m_continuation");
continuationTarget = nextContinuation.TryGetObjectField("_target");
}
}
ClrObject items = continuationObject.TryGetObjectField("_items");
if (!items.IsNull && items.IsArray && items.ContainsPointers)
{
foreach (ClrObject promise in items.EnumerateReferences(true))
{
if (!promise.IsNull)
{
ClrObject innerContinuationObject = promise.TryGetObjectField("m_continuationObject");
if (!innerContinuationObject.IsNull)
{
ChainStateMachineBasedOnTaskContinuations(knownStateMachines, stateMachine, innerContinuationObject);
}
else
{
ChainStateMachineBasedOnTaskContinuations(knownStateMachines, stateMachine, promise);
}
}
}
}
}