Skip to content
This repository was archived by the owner on Oct 4, 2021. It is now read-only.

Commit 7a73da3

Browse files
committed
[CorDebug] Invocations rewritten to .net Task API
1 parent ae4eac9 commit 7a73da3

File tree

2 files changed

+109
-85
lines changed

2 files changed

+109
-85
lines changed

main/src/addins/MonoDevelop.Debugger.Win32/Mono.Debugging.Win32/CorDebuggerSession.cs

Lines changed: 23 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ public static int EvaluationTimestamp {
7979
get { return evaluationTimestamp; }
8080
}
8181

82+
internal CorProcess Process
83+
{
84+
get
85+
{
86+
return process;
87+
}
88+
}
8289

8390
public override void Dispose ( )
8491
{
@@ -912,6 +919,7 @@ protected override void OnNextLine ( )
912919
void Step (bool into)
913920
{
914921
try {
922+
ObjectAdapter.CancelAsyncOperations ();
915923
if (stepper != null) {
916924
CorFrame frame = activeThread.ActiveFrame;
917925
ISymbolReader reader = GetReaderForModule (frame.Function.Module.Name);
@@ -955,7 +963,7 @@ void Step (bool into)
955963
process.Continue (false);
956964
}
957965
} catch (Exception e) {
958-
OnDebuggerOutput (true, e.ToString ());
966+
DebuggerLoggingService.LogError ("Exception on Step()", e);
959967
}
960968
}
961969

@@ -1065,80 +1073,30 @@ public CorValue RuntimeInvoke (CorEvaluationContext ctx, CorFunction function, C
10651073
args[0] = thisObj;
10661074
arguments.CopyTo (args, 1);
10671075
}
1068-
1069-
CorMethodCall mc = new CorMethodCall ();
1070-
CorValue exception = null;
1071-
CorEval eval = ctx.Eval;
1072-
1073-
EvalEventHandler completeHandler = delegate (object o, CorEvalEventArgs eargs) {
1074-
OnEndEvaluating ();
1075-
mc.DoneEvent.Set ();
1076-
eargs.Continue = false;
1077-
};
1078-
1079-
EvalEventHandler exceptionHandler = delegate (object o, CorEvalEventArgs eargs) {
1080-
OnEndEvaluating ();
1081-
exception = eargs.Eval.Result;
1082-
mc.DoneEvent.Set ();
1083-
eargs.Continue = false;
1084-
};
1085-
1086-
process.OnEvalComplete += completeHandler;
1087-
process.OnEvalException += exceptionHandler;
1088-
1089-
mc.OnInvoke = delegate {
1090-
if (function.GetMethodInfo (this).Name == ".ctor")
1091-
eval.NewParameterizedObject (function, typeArgs, args);
1092-
else
1093-
eval.CallParameterizedFunction (function, typeArgs, args);
1094-
process.SetAllThreadsDebugState (CorDebugThreadState.THREAD_SUSPEND, ctx.Thread);
1095-
ClearEvalStatus ();
1096-
OnStartEvaluating ();
1097-
process.Continue (false);
1098-
};
1099-
mc.OnAbort = delegate {
1100-
eval.Abort ();
1101-
};
1102-
mc.OnGetDescription = delegate {
1103-
MethodInfo met = function.GetMethodInfo (ctx.Session);
1104-
if (met != null)
1105-
return met.DeclaringType.FullName + "." + met.Name;
1106-
else
1107-
return "<Unknown>";
1108-
};
1109-
1076+
var methodCall = new CorMethodCall (ctx, function, typeArgs, args);
11101077
try {
1111-
ObjectAdapter.AsyncExecute (mc, ctx.Options.EvaluationTimeout);
1112-
}
1113-
finally {
1114-
process.OnEvalComplete -= completeHandler;
1115-
process.OnEvalException -= exceptionHandler;
1116-
}
1117-
1118-
WaitUntilStopped ();
1119-
if (exception != null) {
1120-
/* ValueReference<CorValue, CorType> msg = ctx.Adapter.GetMember (ctx, val, "Message");
1121-
if (msg != null) {
1122-
string s = msg.ObjectValue as string;
1123-
mc.ExceptionMessage = s;
1078+
var result = ObjectAdapter.InvokeSync (methodCall, ctx.Options.EvaluationTimeout);
1079+
if (result.ResultIsException) {
1080+
var vref = new CorValRef (result.Result);
1081+
throw new EvaluatorExceptionThrownException (vref, ObjectAdapter.GetValueTypeName (ctx, vref));
11241082
}
1125-
else
1126-
mc.ExceptionMessage = "Evaluation failed.";*/
1127-
CorValRef vref = new CorValRef (exception);
1128-
throw new EvaluatorException ("Evaluation failed: " + ObjectAdapter.GetValueTypeName (ctx, vref));
1129-
}
11301083

1131-
return eval.Result;
1084+
WaitUntilStopped ();
1085+
return result.Result;
1086+
}
1087+
catch (COMException ex) {
1088+
throw new EvaluatorException (ex.Message);
1089+
}
11321090
}
11331091

1134-
void OnStartEvaluating ( )
1092+
internal void OnStartEvaluating ( )
11351093
{
11361094
lock (debugLock) {
11371095
evaluating = true;
11381096
}
11391097
}
11401098

1141-
void OnEndEvaluating ( )
1099+
internal void OnEndEvaluating ( )
11421100
{
11431101
lock (debugLock) {
11441102
evaluating = false;
@@ -1235,7 +1193,7 @@ public void WaitUntilStopped ()
12351193
}
12361194
}
12371195

1238-
void ClearEvalStatus ( )
1196+
internal void ClearEvalStatus ( )
12391197
{
12401198
foreach (CorProcess p in dbg.Processes) {
12411199
if (p.Id == processId) {
Lines changed: 86 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,113 @@
11
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Microsoft.Samples.Debugging.CorDebug;
4+
using Microsoft.Samples.Debugging.CorDebug.NativeApi;
25
using Mono.Debugging.Evaluation;
36

47
namespace Mono.Debugging.Win32
58
{
6-
class CorMethodCall: AsyncOperation
9+
class CorMethodCall: AsyncOperationBase<CorValue>
710
{
8-
public delegate void CallCallback ( );
9-
public delegate string DescriptionCallback ( );
11+
readonly CorEvaluationContext context;
12+
readonly CorFunction function;
13+
readonly CorType[] typeArgs;
14+
readonly CorValue[] args;
1015

11-
public CallCallback OnInvoke;
12-
public CallCallback OnAbort;
13-
public DescriptionCallback OnGetDescription;
16+
readonly CorEval eval;
1417

15-
public ManualResetEvent DoneEvent = new ManualResetEvent (false);
18+
public CorMethodCall (CorEvaluationContext context, CorFunction function, CorType[] typeArgs, CorValue[] args)
19+
{
20+
this.context = context;
21+
this.function = function;
22+
this.typeArgs = typeArgs;
23+
this.args = args;
24+
eval = context.Eval;
25+
}
1626

17-
public override string Description
27+
void ProcessOnEvalComplete (object sender, CorEvalEventArgs evalArgs)
28+
{
29+
DoProcessEvalFinished (evalArgs, false);
30+
}
31+
32+
void ProcessOnEvalException (object sender, CorEvalEventArgs evalArgs)
1833
{
19-
get { return OnGetDescription (); }
34+
DoProcessEvalFinished (evalArgs, true);
2035
}
2136

22-
public override void Invoke ( )
37+
void DoProcessEvalFinished (CorEvalEventArgs evalArgs, bool isException)
2338
{
24-
OnInvoke ();
39+
if (evalArgs.Eval != eval)
40+
return;
41+
context.Session.OnEndEvaluating ();
42+
evalArgs.Continue = false;
43+
tcs.TrySetResult(new OperationResult<CorValue> (evalArgs.Eval.Result, isException));
2544
}
2645

27-
public override void Abort ( )
46+
void SubscribeOnEvals ()
2847
{
29-
OnAbort ();
48+
context.Session.Process.OnEvalComplete += ProcessOnEvalComplete;
49+
context.Session.Process.OnEvalException += ProcessOnEvalException;
3050
}
3151

32-
public override void Shutdown ( )
52+
void UnSubcribeOnEvals ()
53+
{
54+
context.Session.Process.OnEvalComplete -= ProcessOnEvalComplete;
55+
context.Session.Process.OnEvalException -= ProcessOnEvalException;
56+
}
57+
58+
public override string Description
3359
{
34-
try {
35-
Abort ();
60+
get
61+
{
62+
var met = function.GetMethodInfo (context.Session);
63+
if (met == null)
64+
return "<Unknown>";
65+
if (met.DeclaringType == null)
66+
return met.Name;
67+
return met.DeclaringType.FullName + "." + met.Name;
3668
}
37-
catch {
69+
}
70+
71+
readonly TaskCompletionSource<OperationResult<CorValue>> tcs = new TaskCompletionSource<OperationResult<CorValue>> ();
72+
const int DelayAfterAbort = 500;
73+
74+
protected override void AfterCancelledImpl (int elapsedAfterCancelMs)
75+
{
76+
if (tcs.TrySetCanceled ()) {
77+
// really cancelled for the first time not before. so we should check that we awaited necessary amout of time after Abort() call
78+
// else if we return too earle after Abort() the process may be PROCESS_NOT_SYNCHRONIZED
79+
if (elapsedAfterCancelMs < DelayAfterAbort) {
80+
Thread.Sleep (DelayAfterAbort - elapsedAfterCancelMs);
81+
}
3882
}
39-
DoneEvent.Set ();
83+
context.Session.OnEndEvaluating ();
4084
}
4185

42-
public override bool WaitForCompleted (int timeout)
86+
protected override Task<OperationResult<CorValue>> InvokeAsyncImpl (CancellationToken token)
87+
{
88+
SubscribeOnEvals ();
89+
90+
if (function.GetMethodInfo (context.Session).Name == ".ctor")
91+
eval.NewParameterizedObject (function, typeArgs, args);
92+
else
93+
eval.CallParameterizedFunction (function, typeArgs, args);
94+
context.Session.Process.SetAllThreadsDebugState (CorDebugThreadState.THREAD_SUSPEND, context.Thread);
95+
context.Session.ClearEvalStatus ();
96+
context.Session.OnStartEvaluating ();
97+
context.Session.Process.Continue (false);
98+
Task = tcs.Task;
99+
// Don't pass token here, because it causes immediately task cancellation which must be performed by debugger event or real timeout
100+
// ReSharper disable once MethodSupportsCancellation
101+
return Task.ContinueWith (task => {
102+
UnSubcribeOnEvals ();
103+
return task.Result;
104+
});
105+
}
106+
107+
108+
protected override void CancelImpl ( )
43109
{
44-
return DoneEvent.WaitOne (timeout, false);
110+
eval.Abort ();
45111
}
46112
}
47113
}

0 commit comments

Comments
 (0)