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

Commit afd8303

Browse files
committed
[CorDebug] Invocations rewritten to .Net Task API
1 parent 4093f13 commit afd8303

File tree

2 files changed

+105
-84
lines changed

2 files changed

+105
-84
lines changed

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

Lines changed: 19 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ public static int EvaluationTimestamp {
109109
get { return evaluationTimestamp; }
110110
}
111111

112+
internal CorProcess Process
113+
{
114+
get
115+
{
116+
return process;
117+
}
118+
}
112119

113120
public override void Dispose ( )
114121
{
@@ -1340,49 +1347,16 @@ public CorValue RuntimeInvoke (CorEvaluationContext ctx, CorFunction function, C
13401347
arguments.CopyTo (args, 1);
13411348
}
13421349

1343-
CorMethodCall mc = new CorMethodCall ();
1344-
CorValue exception = null;
1345-
CorEval eval = ctx.Eval;
1346-
1347-
DebugEventHandler<CorEvalEventArgs> completeHandler = delegate (object o, CorEvalEventArgs eargs) {
1348-
OnEndEvaluating ();
1349-
mc.DoneEvent.Set ();
1350-
eargs.Continue = false;
1351-
};
1352-
1353-
DebugEventHandler<CorEvalEventArgs> exceptionHandler = delegate(object o, CorEvalEventArgs eargs) {
1354-
OnEndEvaluating ();
1355-
exception = eargs.Eval.Result;
1356-
mc.DoneEvent.Set ();
1357-
eargs.Continue = false;
1358-
};
1359-
1360-
process.OnEvalComplete += completeHandler;
1361-
process.OnEvalException += exceptionHandler;
1362-
1363-
mc.OnInvoke = delegate {
1364-
if (function.GetMethodInfo (this).Name == ".ctor")
1365-
eval.NewParameterizedObject (function, typeArgs, args);
1366-
else
1367-
eval.CallParameterizedFunction (function, typeArgs, args);
1368-
process.SetAllThreadsDebugState (CorDebugThreadState.THREAD_SUSPEND, ctx.Thread);
1369-
ClearEvalStatus ();
1370-
OnStartEvaluating ();
1371-
process.Continue (false);
1372-
};
1373-
mc.OnAbort = delegate {
1374-
eval.Abort ();
1375-
};
1376-
mc.OnGetDescription = delegate {
1377-
MethodInfo met = function.GetMethodInfo (ctx.Session);
1378-
if (met != null)
1379-
return met.DeclaringType.FullName + "." + met.Name;
1380-
else
1381-
return "<Unknown>";
1382-
};
1383-
1350+
var methodCall = new CorMethodCall (ctx, function, typeArgs, args);
13841351
try {
1385-
ObjectAdapter.AsyncExecute (mc, ctx.Options.EvaluationTimeout);
1352+
var result = ObjectAdapter.InvokeSync (methodCall, ctx.Options.EvaluationTimeout);
1353+
if (result.ResultIsException) {
1354+
var vref = new CorValRef (result.Result);
1355+
throw new EvaluatorExceptionThrownException (vref, ObjectAdapter.GetValueTypeName (ctx, vref));
1356+
}
1357+
1358+
WaitUntilStopped ();
1359+
return result.Result;
13861360
}
13871361
catch (COMException ex) {
13881362
// eval exception is a 'good' exception that should be shown in value box
@@ -1392,35 +1366,16 @@ public CorValue RuntimeInvoke (CorEvaluationContext ctx, CorFunction function, C
13921366
throw evalException;
13931367
throw;
13941368
}
1395-
finally {
1396-
process.OnEvalComplete -= completeHandler;
1397-
process.OnEvalException -= exceptionHandler;
1398-
}
1399-
1400-
WaitUntilStopped ();
1401-
if (exception != null) {
1402-
/* ValueReference<CorValue, CorType> msg = ctx.Adapter.GetMember (ctx, val, "Message");
1403-
if (msg != null) {
1404-
string s = msg.ObjectValue as string;
1405-
mc.ExceptionMessage = s;
1406-
}
1407-
else
1408-
mc.ExceptionMessage = "Evaluation failed.";*/
1409-
CorValRef vref = new CorValRef (exception);
1410-
throw new EvaluatorException ("Evaluation failed: " + ObjectAdapter.GetValueTypeName (ctx, vref));
1411-
}
1412-
1413-
return eval.Result;
14141369
}
14151370

1416-
void OnStartEvaluating ( )
1371+
internal void OnStartEvaluating ( )
14171372
{
14181373
lock (debugLock) {
14191374
evaluating = true;
14201375
}
14211376
}
14221377

1423-
void OnEndEvaluating ( )
1378+
internal void OnEndEvaluating ( )
14241379
{
14251380
lock (debugLock) {
14261381
evaluating = false;
@@ -1526,7 +1481,7 @@ public void WaitUntilStopped ()
15261481
}
15271482
}
15281483

1529-
void ClearEvalStatus ( )
1484+
internal void ClearEvalStatus ( )
15301485
{
15311486
foreach (CorProcess p in dbg.Processes) {
15321487
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)