Skip to content

Commit

Permalink
Convert to Task
Browse files Browse the repository at this point in the history
  • Loading branch information
WardenGnaw committed Jan 21, 2021
1 parent de74135 commit c9b7029
Showing 1 changed file with 166 additions and 140 deletions.
306 changes: 166 additions & 140 deletions src/OpenDebugAD7/AD7DebugSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1305,198 +1305,224 @@ protected override void HandlePauseRequestAsync(IRequestResponder<PauseArguments
responder.SetResponse(new PauseResponse());
}

protected override void HandleStackTraceRequestAsync(IRequestResponder<StackTraceArguments, StackTraceResponse> responder)
protected override async void HandleStackTraceRequestAsync(IRequestResponder<StackTraceArguments, StackTraceResponse> responder)
{
int threadReference = responder.Arguments.ThreadId;
int startFrame = responder.Arguments.StartFrame.GetValueOrDefault(0);
int levels = responder.Arguments.Levels.GetValueOrDefault(0);

StackTraceResponse response = new StackTraceResponse()
try
{
TotalFrames = 0
};
int threadReference = responder.Arguments.ThreadId;
int startFrame = responder.Arguments.StartFrame.GetValueOrDefault(0);
int levels = responder.Arguments.Levels.GetValueOrDefault(0);

// Make sure we are stopped and receiving valid input or else return an empty stack trace
if (m_isStopped && startFrame >= 0 && levels >= 0)
{
ThreadFrameEnumInfo frameEnumInfo = null;
IDebugThread2 thread;
lock (m_threads)
StackTraceResponse response = new StackTraceResponse()
{
if (m_threads.TryGetValue(threadReference, out thread))
{
enum_FRAMEINFO_FLAGS flags = enum_FRAMEINFO_FLAGS.FIF_FUNCNAME | // need a function name
enum_FRAMEINFO_FLAGS.FIF_FRAME | // need a frame object
enum_FRAMEINFO_FLAGS.FIF_FLAGS |
enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP;

uint radix = Constants.EvaluationRadix;
TotalFrames = 0
};

if (responder.Arguments.Format != null)
// Make sure we are stopped and receiving valid input or else return an empty stack trace
if (m_isStopped && startFrame >= 0 && levels >= 0)
{
ThreadFrameEnumInfo frameEnumInfo = null;
IDebugThread2 thread;
lock (m_threads)
{
if (m_threads.TryGetValue(threadReference, out thread))
{
StackFrameFormat format = responder.Arguments.Format;
enum_FRAMEINFO_FLAGS flags = enum_FRAMEINFO_FLAGS.FIF_FUNCNAME | // need a function name
enum_FRAMEINFO_FLAGS.FIF_FRAME | // need a frame object
enum_FRAMEINFO_FLAGS.FIF_FLAGS |
enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP;

if (format.Hex == true)
{
radix = 16;
}
uint radix = Constants.EvaluationRadix;

if (format.Line == true)
if (responder.Arguments.Format != null)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES;
}
StackFrameFormat format = responder.Arguments.Format;

if (format.Module == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE;
}
if (format.Hex == true)
{
radix = 16;
}

if (format.Parameters == true)
if (format.Line == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES;
}

if (format.Module == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE;
}

if (format.Parameters == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS;
}

if (format.ParameterNames == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
}

if (format.ParameterTypes == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES;
}

if (format.ParameterValues == true)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES;
}
}
else
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS;
// No formatting flags provided in the request - use the default format, which includes the module name and argument names / types
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
}

if (format.ParameterNames == true)
if (m_settingsCallback != null)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
// MIEngine generally gets the radix from IDebugSettingsCallback110 rather than using the radix passed
m_settingsCallback.Radix = radix;
}

if (format.ParameterTypes == true)
ErrorBuilder eb = new ErrorBuilder(() => AD7Resources.Error_Scenario_StackTrace);

try
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES;
}
eb.CheckHR(thread.EnumFrameInfo(flags, radix, out IEnumDebugFrameInfo2 frameEnum));
eb.CheckHR(frameEnum.GetCount(out uint totalFrames));

if (format.ParameterValues == true)
frameEnumInfo = new ThreadFrameEnumInfo(frameEnum, totalFrames);
}
catch (AD7Exception ex)
{
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES;
responder.SetError(new ProtocolException(ex.Message, ex));
return;
}
}
else
{
// No formatting flags provided in the request - use the default format, which includes the module name and argument names / types
flags |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES |
enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES;
// Invalid thread specified
responder.SetError(new ProtocolException(String.Format(CultureInfo.CurrentCulture, AD7Resources.Error_PropertyInvalid, StackTraceRequest.RequestType, "threadId")));
return;
}
}

if (m_settingsCallback != null)
if (startFrame < frameEnumInfo.TotalFrames)
{
if (startFrame != frameEnumInfo.CurrentPosition)
{
// MIEngine generally gets the radix from IDebugSettingsCallback110 rather than using the radix passed
m_settingsCallback.Radix = radix;
}
frameEnumInfo.FrameEnum.Reset();
frameEnumInfo.CurrentPosition = (uint)startFrame;

ErrorBuilder eb = new ErrorBuilder(() => AD7Resources.Error_Scenario_StackTrace);
if (startFrame > 0)
{
frameEnumInfo.FrameEnum.Skip((uint)startFrame);
}
}

try
if (levels == 0)
{
eb.CheckHR(thread.EnumFrameInfo(flags, radix, out IEnumDebugFrameInfo2 frameEnum));
eb.CheckHR(frameEnum.GetCount(out uint totalFrames));

frameEnumInfo = new ThreadFrameEnumInfo(frameEnum, totalFrames);
// take the rest of the stack frames
levels = (int)frameEnumInfo.TotalFrames - startFrame;
}
catch (AD7Exception ex)
else
{
responder.SetError(new ProtocolException(ex.Message, ex));
return;
levels = Math.Min((int)frameEnumInfo.TotalFrames - startFrame, levels);
}
}
else
{
// Invalid thread specified
responder.SetError(new ProtocolException(String.Format(CultureInfo.CurrentCulture, AD7Resources.Error_PropertyInvalid, StackTraceRequest.RequestType, "threadId")));
return;
}
}

if (startFrame < frameEnumInfo.TotalFrames)
{
if (startFrame != frameEnumInfo.CurrentPosition)
{
frameEnumInfo.FrameEnum.Reset();
frameEnumInfo.CurrentPosition = (uint)startFrame;
var frameInfoArray = new FRAMEINFO[levels];
uint framesFetched = 0;
frameEnumInfo.FrameEnum.Next((uint)frameInfoArray.Length, frameInfoArray, ref framesFetched);
frameEnumInfo.CurrentPosition += framesFetched;

if (startFrame > 0)
for (int i = 0; i < framesFetched; i++)
{
frameEnumInfo.FrameEnum.Skip((uint)startFrame);
}
}

if (levels == 0)
{
// take the rest of the stack frames
levels = (int)frameEnumInfo.TotalFrames - startFrame;
}
else
{
levels = Math.Min((int)frameEnumInfo.TotalFrames - startFrame, levels);
}

var frameInfoArray = new FRAMEINFO[levels];
uint framesFetched = 0;
frameEnumInfo.FrameEnum.Next((uint)frameInfoArray.Length, frameInfoArray, ref framesFetched);
frameEnumInfo.CurrentPosition += framesFetched;

for (int i = 0; i < framesFetched; i++)
{
// TODO: annotated frames?
var frameInfo = frameInfoArray[i];
IDebugStackFrame2 frame = frameInfo.m_pFrame;
// TODO: annotated frames?
var frameInfo = frameInfoArray[i];
IDebugStackFrame2 frame = frameInfo.m_pFrame;

int frameReference = 0;
TextPositionTuple textPosition = TextPositionTuple.Nil;
int frameReference = 0;
TextPositionTuple textPosition = TextPositionTuple.Nil;

if (frame != null)
{
frameReference = m_frameHandles.Create(frame);
textPosition = TextPositionTuple.GetTextPositionOfFrame(m_pathConverter, frame) ?? TextPositionTuple.Nil;
}
if (frame != null)
{
frameReference = m_frameHandles.Create(frame);
textPosition = TextPositionTuple.GetTextPositionOfFrame(m_pathConverter, frame) ?? TextPositionTuple.Nil;
}

int? moduleId = null;
IDebugModule2 module = frameInfo.m_pModule;
if (module != null)
{
lock (m_moduleMap)
int? moduleId = null;
IDebugModule2 module = frameInfo.m_pModule;
if (module != null)
{
if (m_moduleMap.TryGetValue(module, out int mapModuleId))
lock (m_moduleMap)
{
moduleId = mapModuleId;
if (m_moduleMap.TryGetValue(module, out int mapModuleId))
{
moduleId = mapModuleId;
}
}
}

response.StackFrames.Add(new ProtocolMessages.StackFrame()
{
Id = frameReference,
Name = frameInfo.m_bstrFuncName,
Source = textPosition.Source,
Line = textPosition.Line,
Column = textPosition.Column,
ModuleId = moduleId
});
}

response.StackFrames.Add(new ProtocolMessages.StackFrame()
if (!IsClientVS)
{
Id = frameReference,
Name = frameInfo.m_bstrFuncName,
Source = textPosition.Source,
Line = textPosition.Line,
Column = textPosition.Column,
ModuleId = moduleId
});
}
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
try
{
CancellationToken cancellationToken = cancellationTokenSource.Token;
Task[] frameTasks = response.StackFrames.Select(frame => Task.Run(() =>
{
cancellationToken.ThrowIfCancellationRequested();
if (frame.Source != null && !File.Exists(frame.Source.Path))
{
cancellationToken.ThrowIfCancellationRequested();
// mark the stack frame to be skipped by default
frame.Source.PresentationHint = Source.PresentationHintValue.Deemphasize;
}
})).ToArray();

if (!IsClientVS)
{
Parallel.ForEach(response.StackFrames, frame =>
{
if (frame.Source == null)
return;
var task = new Task<bool>(() => File.Exists(frame.Source.Path));
task.Start();
if (task.Wait(500) && !task.Result)
Task allFramesComplete = Task.WhenAll(frameTasks);
Task timeoutTask = Task.Delay(20000, cancellationToken);
try
{
await Task.WhenAny(allFramesComplete, timeoutTask);
}
catch (Exception e)
{
Debug.Fail("Ignoring exception computing frame state: " + e.ToString());
}
}
finally
{
// mark the stack frame to be skipped by default
frame.Source.PresentationHint = Source.PresentationHintValue.Deemphasize;
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
}
});
}
}

response.TotalFrames = (int)frameEnumInfo.TotalFrames;
response.TotalFrames = (int)frameEnumInfo.TotalFrames;
}
}
}

responder.SetResponse(response);
responder.SetResponse(response);
}
catch (Exception e)
{
responder.SetError(new ProtocolException(e.ToString()));
}
}

protected override void HandleScopesRequestAsync(IRequestResponder<ScopesArguments, ScopesResponse> responder)
Expand Down

0 comments on commit c9b7029

Please sign in to comment.