private int GetBusyCount() { var readDone = TargetObject.ReadField <bool>("m_ReadDone"); var reservedCount = TargetObject.ReadField <int>("m_ReservedCount"); var waitListObject = TargetObject.ReadObjectField("m_WaitList"); var waitListSize = waitListObject.ReadField <int>("_size"); var writeListObject = TargetObject.ReadObjectField("m_WriteList"); var writeListSize = writeListObject.ReadField <int>("_size"); return((readDone ? 0 : 1) + 2 * (waitListSize + writeListSize) + reservedCount); }
public void Dump(ILogger logger) { AsyncRecord asyncRecord = new AsyncRecord(TargetObject); if (TargetObject.Type.GetFieldByName("m_stateFlags") != null) { asyncRecord.TaskStateFlags = TargetObject.ReadField <int>("m_stateFlags"); } //DebugObjectFields(); ClrInstanceField?stateMachineField = TargetObject.Type.GetFieldByName("StateMachine"); if (stateMachineField != null) { asyncRecord.IsStateMachine = true; asyncRecord.IsValueType = stateMachineField.IsValueType; int stateFieldOffset = -1; if (asyncRecord.IsValueType) { asyncRecord.StateMachineAddr = new(TargetObject.Address + (ulong)stateMachineField.Offset); asyncRecord.StateMachineMT = new(stateMachineField.Type.MethodTable); //stateFieldOffset = stateMachineField.Type.GetFieldByName("<>1__state").Offset; asyncRecord.StateValue = stateMachineField.Type.GetFieldByName("<>1__state").Read <int>(TargetObject.Address, false); } else { throw new NotImplementedException(); } if (stateFieldOffset >= 0 && (asyncRecord.IsValueType || stateFieldOffset != 0)) { asyncRecord.StateValue = Context.Heap.Runtime.DataTarget.DataReader.Read <int>(asyncRecord.StateMachineAddr.Value + (ulong)stateFieldOffset + 8); } } var stateMachineObject = TargetObject.ReadValueTypeField("StateMachine"); //using (logger.BeginScope(GetAsyncMethodName(stateMachineObject.Type.Name))) { if (stateMachineObject.Type.GetFieldByName("<>1__state") == null) { logger.LogInformation("state is not found. skipping"); return; } var state = stateMachineObject.ReadField <int>("<>1__state"); if (_fullLog) { logger.LogInformation($"__state: {state}"); } if (stateMachineObject.Type.Fields.Any(f => f.Name == "<>4__this")) { var thisObject = stateMachineObject.ReadObjectField("<>4__this"); //logger.LogInformation($"this type = {thisObject.Type.Name}"); logger.LogInformation($"{GetAsyncMethodName(stateMachineObject.Type.Name)} in {thisObject.Type.Name}"); } foreach (var field in stateMachineObject.Type.Fields.Where(field => field.Name.StartsWith("<>u__", StringComparison.Ordinal)).OrderBy(field => field.Name)) { if (!field.Type.IsValueType) { // TODO logger.LogWarning("SKIP if (!field.Type.IsValueClass)"); continue; } var uField = stateMachineObject.ReadValueTypeField(field.Name); if (!uField.Type.Name.StartsWith("System", StringComparison.Ordinal)) { // TODO logger.LogWarning("SKIP if (!uField.Type.Name.StartsWith"); continue; } if (uField.Address == Address.Null.Value) { // TODO logger.LogWarning("SKIP uField.Address == NullAddress"); continue; } if (uField.Type.Name.StartsWith("System.Runtime.CompilerServices.ValueTaskAwaiter", StringComparison.Ordinal)) { var valueValueClass = uField.ReadValueTypeField("_value"); // ValueTask var obj = valueValueClass.ReadObjectField("_obj"); var token = valueValueClass.ReadField <short>("_token"); var continueOnCapturedContext = valueValueClass.ReadField <bool>("_continueOnCapturedContext"); logger.LogInformation($"obj: {obj}\n\ttoken: {token}\n\tcontinueOnCapturedContext: {continueOnCapturedContext}"); // TODO // logger.LogWarning("SKIP System.Runtime.CompilerServices.ValueTaskAwaiter"); continue; } if (uField.Type.Name.StartsWith("System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<", StringComparison.Ordinal)) { var valueTask = uField.ReadValueTypeField("_value"); var valueTaskProxy = new ValueTaskProxy(Context, valueTask); var completed = valueTaskProxy.IsCompleted; } else { ClrObject uTaskObject = uField.ReadObjectField("m_task"); var statusTask = "NULL"; if (!uTaskObject.IsNull) { var taskProxy = new TaskProxy(Context, uTaskObject); statusTask = $"{taskProxy.Status} (IsCompleted:{taskProxy.IsCompleted}) {field.Type.Name}"; // TASK is System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Npgsql.NpgsqlReadBuffer+<>c__DisplayClass31_0+<<Ensure>g__EnsureLong|0>d, Npgsql]] foreach (var refAddress in Context.HeapIndex.GetReferencesTo(uTaskObject.Address)) { var refObject = Context.Heap.GetObject(refAddress); if (_fullLog) { logger.LogInformation($"ref by {refObject}"); } if (refObject.Type.EnumerateInterfaces().Any(clrInterface => clrInterface.Name == "System.Runtime.CompilerServices.IAsyncStateMachineBox")) { new AsyncStateMachineBoxProxy(Context, refObject).Dump(logger); } } } //if (_fullLog) logger.LogInformation($"{field.Name}: {statusTask}"); } } } }