Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2018-02-10 03:15:32 +0300
committerGitHub <noreply@github.com>2018-02-10 03:15:32 +0300
commit284c5afdf4363aec956ce370c86fc44458fffe6c (patch)
tree643398d288ca3dce4846b257192032b61d1d98da
parentdcda4c77bc910bc3ece378007a3c79a14294b15d (diff)
Bug 60088 - Assertion at ../../../../external/mono/mono/mini/debugger-agent.c:4765, condition `array->len == 1' not met (#6902)
Problem was that I didn't consider `async void` method when adding that assert
-rw-r--r--mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs19
-rw-r--r--mcs/class/Mono.Debugger.Soft/Test/dtest.cs20
-rw-r--r--mono/mini/debugger-agent.c35
3 files changed, 62 insertions, 12 deletions
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
index 743047ef3f1..97202372c77 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
@@ -322,6 +322,12 @@ public class Tests : TestsBase, ITest2
new Tests ().attach ();
return 0;
}
+ if (args.Length > 0 && args [0] == "step-out-void-async") {
+ var wait = new ManualResetEvent (false);
+ step_out_void_async (wait);
+ wait.WaitOne ();//Don't exist until step_out_void_async is executed...
+ return 0;
+ }
assembly_load ();
breakpoints ();
single_stepping ();
@@ -1742,6 +1748,19 @@ public class Tests : TestsBase, ITest2
{
UninitializedClass.Call();//Breakpoint here and step in
}
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ static async void step_out_void_async (ManualResetEvent wait)
+ {
+ await Task.Yield ();
+ step_out_void_async_2 ();
+ wait.Set ();
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ static void step_out_void_async_2 ()
+ {
+ }
}
public class SentinelClass : MarshalByRefObject {
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
index 78be9f85a2d..088fe98b087 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
@@ -10,6 +10,7 @@ using Diag = System.Diagnostics;
using System.Linq;
using System.IO;
using System.Security.Cryptography;
+using System.Threading.Tasks;
using NUnit.Framework;
@@ -4287,6 +4288,25 @@ public class DebuggerTests
}
[Test]
+ public void StepOutAsync () {
+ vm.Detach ();
+ Start (new string [] { "dtest-app.exe", "step-out-void-async" });
+ var e = run_until ("step_out_void_async_2");
+ create_step (e);
+ var e2 = step_out ();
+ assert_location (e2, "MoveNext");//we are in step_out_void_async
+ step_req.Disable ();
+ step_req.Depth = StepDepth.Out;
+ step_req.Enable ();
+ vm.Resume ();
+ var e3 = GetNextEvent ();
+ //after step-out from async void, execution should continue
+ //and runtime should exit
+ Assert.IsTrue (e3 is VMDeathEvent, e3.GetType().FullName);
+ vm = null;
+ }
+
+ [Test]
[Category("NotWorking")]
public void ShouldCorrectlyStepOverOnExitFromArgsAfterStepInMethodParameter() {
Event e = run_until ("ss_nested_with_two_args_wrapper");
diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c
index 5c37e009152..abacc567379 100644
--- a/mono/mini/debugger-agent.c
+++ b/mono/mini/debugger-agent.c
@@ -4811,7 +4811,10 @@ get_set_notification_method (MonoClass* async_builder_class)
ERROR_DECL (error);
GPtrArray* array = mono_class_get_methods_by_name (async_builder_class, "SetNotificationForWaitCompletion", 0x24, FALSE, FALSE, error);
mono_error_assert_ok (error);
- g_assert (array->len == 1);
+ if (array->len == 0) {
+ g_ptr_array_free (array, TRUE);
+ return NULL;
+ }
MonoMethod* set_notification_method = (MonoMethod *)g_ptr_array_index (array, 0);
g_ptr_array_free (array, TRUE);
return set_notification_method;
@@ -4897,7 +4900,9 @@ get_this_async_id (StackFrame *frame)
return get_objid (obj);
}
-static void
+// Returns true if TaskBuilder has NotifyDebuggerOfWaitCompletion method
+// false if not(AsyncVoidBuilder)
+static gboolean
set_set_notification_for_wait_completion_flag (StackFrame *frame)
{
MonoClassField *builder_field = mono_class_get_field_from_name (frame->method->klass, "<>t__builder");
@@ -4909,11 +4914,15 @@ set_set_notification_for_wait_completion_flag (StackFrame *frame)
gboolean arg = TRUE;
ERROR_DECL (error);
args [0] = &arg;
- mono_runtime_invoke_checked (get_set_notification_method (mono_class_from_mono_type (builder_field->type)), builder, args, error);
+ MonoMethod* method = get_set_notification_method (mono_class_from_mono_type (builder_field->type));
+ if (method == NULL)
+ return FALSE;
+ mono_runtime_invoke_checked (method, builder, args, error);
mono_error_assert_ok (error);
+ return TRUE;
}
-static MonoMethod* notify_debugger_of_wait_completion_method_cache = NULL;
+static MonoMethod* notify_debugger_of_wait_completion_method_cache;
static MonoMethod*
get_notify_debugger_of_wait_completion_method (void)
@@ -5695,14 +5704,16 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI
ss_req->depth = STEP_DEPTH_OUT;//setting depth to step-out is important, don't inline IF, because code later depends on this
}
if (ss_req->depth == STEP_DEPTH_OUT) {
- set_set_notification_for_wait_completion_flag (frames [0]);
- ss_req->async_id = get_this_async_id (frames [0]);
- ss_req->async_stepout_method = get_notify_debugger_of_wait_completion_method ();
- ss_bp_add_one (ss_req, &ss_req_bp_count, &ss_req_bp_cache, ss_req->async_stepout_method, 0);
- if (ss_req_bp_cache)
- g_hash_table_destroy (ss_req_bp_cache);
- mono_debug_free_method_async_debug_info (asyncMethod);
- return;
+ //If we are inside `async void` method, do normal step-out
+ if (set_set_notification_for_wait_completion_flag (frames [0])) {
+ ss_req->async_id = get_this_async_id (frames [0]);
+ ss_req->async_stepout_method = get_notify_debugger_of_wait_completion_method ();
+ ss_bp_add_one (ss_req, &ss_req_bp_count, &ss_req_bp_cache, ss_req->async_stepout_method, 0);
+ if (ss_req_bp_cache)
+ g_hash_table_destroy (ss_req_bp_cache);
+ mono_debug_free_method_async_debug_info (asyncMethod);
+ return;
+ }
}
}