Bug 60088

Summary: Assertion at ../../../../external/mono/mono/mini/debugger-agent.c:4765, condition `array->len == 1' not met
Product: iOS Reporter: Rolf Bjarne Kvinge [MSFT] <rolf>
Component: Mono runtime / AOT compilerAssignee: Zoltan Varga <vargaz>
Severity: normal CC: brendan.zagaeski, michael.e.miller1, mono-bugs+monotouch, sebastien, stephan
Priority: ---    
Version: master   
Target Milestone: 15.7   
Hardware: PC   
OS: Mac OS   
Related Links: https://bugzilla.xamarin.com/show_bug.cgi?id=59015
Tags: Is this bug a regression?: ---
Last known good build:

Description Rolf Bjarne Kvinge [MSFT] 2017-10-10 12:46:30 UTC

* Use repro solution for bug #59015 (https://bugzilla.xamarin.com/attachment.cgi?id=24432)
* Put a breakpoint on MainPage.xaml.cs:44 ("base.OnAppearing();")
* Run in the simulator.
* When the breakpoint hits, press "Step Into" 3 times. The third time the app will crash:

> 2017-10-10 14:38:00.288 sampleSIGABRT.iOS[63558:4813548] error: * Assertion at ../../../../external/mono/mono/mini/debugger-agent.c:4765, condition `array->len == 1' not met

Complete application output: https://gist.github.com/rolfbjarne/fab23634a4c387cc8a1446da51219c9f

A lldb session shows that the runtime looks for the method "SetNotificationForWaitCompletion" on the class "AsyncVoidMethodBuilder":

> (lldb)  
> Process 62527 stopped
> * thread #1, name = 'tid_403', queue = 'com.apple.main-thread', stop reason = instruction step into
>     frame #0: 0x000000010a6f9853 sampleSIGABRT.iOS`ss_start [inlined] get_set_notification_method(async_builder_class=0x00007fd537343e78) at debugger-agent.c:4763 [opt]
>    4760	get_set_notification_method (MonoClass* async_builder_class)
>    4761	{
>    4762		MonoError error;
> -> 4763		GPtrArray* array = mono_class_get_methods_by_name (async_builder_class, "SetNotificationForWaitCompletion", 0x24, FALSE, FALSE, &error);
>    4764		mono_error_assert_ok (&error);
>    4765		g_assert (array->len == 1);
>    4766		MonoMethod* set_notification_method = (MonoMethod *)g_ptr_array_index (array, 0);
> Target 0: (sampleSIGABRT.iOS) stopped.
> (lldb) p async_builder_class->name
> (const char *) $9 = 0x0000000135acf253 "AsyncVoidMethodBuilder"
> (lldb) next
> Process 62527 stopped
> * thread #1, name = 'tid_403', queue = 'com.apple.main-thread', stop reason = step over
>     frame #0: 0x000000010a6f9872 sampleSIGABRT.iOS`ss_start [inlined] get_set_notification_method(async_builder_class=<unavailable>) at debugger-agent.c:4764 [opt]
>    4761	{
>    4762		MonoError error;
>    4763		GPtrArray* array = mono_class_get_methods_by_name (async_builder_class, "SetNotificationForWaitCompletion", 0x24, FALSE, FALSE, &error);
> -> 4764		mono_error_assert_ok (&error);
>    4765		g_assert (array->len == 1);
>    4766		MonoMethod* set_notification_method = (MonoMethod *)g_ptr_array_index (array, 0);
>    4767		g_ptr_array_free (array, TRUE);
> Target 0: (sampleSIGABRT.iOS) stopped.
> (lldb) p array->len
> (guint) $11 = 0

but from what I can see [1], that method does not exist in that class.

[1]: https://github.com/mono/mono/blob/344a3ec4e1532d5cbd9abeb6926771fae260f005/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs#L39-L265
Comment 2 Rolf Bjarne Kvinge [MSFT] 2017-10-10 12:50:52 UTC
Full version info: https://gist.github.com/rolfbjarne/68a469f0ceffd50c769e49d2aac53d0b
Comment 3 Zoltan Varga 2017-10-21 02:41:09 UTC
I think that class needs to be added to tools/linker/MobileMarkStep.cs.
Comment 4 Rolf Bjarne Kvinge [MSFT] 2017-10-23 10:02:34 UTC
@Zoltan, telling the linker to preserve the class doesn't help much if the runtime looks for a method inside that class that doesn't exist in the first place.

I don't know whether the runtime is looking for something it shouldn't be looking for, or if it's a mistake that the method doesn't exist.
Comment 5 Mike Miller 2017-12-07 17:54:50 UTC
This happens for me, but it is not nearly so specific.  It happens if I'm stepping through/over asynchronous code.  It runs fine as long as I'm not trying to step with the debugger.  

When I do that, it often fails with the error - and once it starts, it doesn't stop, unless I stop trying to step through that piece of code, anyway.  Also, there doesn't seem be any real predictability to it other than it being asynchronous code.
Comment 6 Stephan 2017-12-07 21:23:44 UTC
I can only confirm what Mike Miller says. It happens when debugging async methods. I'm using Xamarin.Forms
Comment 7 Stephan 2017-12-07 21:25:15 UTC
One addition regarding setup. I'm running the app on Android and developing on Windows (Visual Studio).
Comment 8 Mike Miller 2017-12-07 21:34:11 UTC
I am also using and Net Standard 2.0.  My project supports iOS, Android, and UWP.  I am developing in Visual Studio on Windows using version 2.4.5.
Comment 9 Sebastien Pouliot 2018-01-08 21:03:53 UTC
@Zoltan, I agree with Rolf's comment #4. The type that the mono runtime is looking up does not match the managed/BCL type location.
Comment 10 Zoltan Varga 2018-01-24 04:26:08 UTC
Comment 11 Sebastien Pouliot 2018-02-13 20:02:06 UTC
@Zoltan can this be back ported to 2017-12 ?
it can wait after we merge it (in xamarin-macios/master)
Comment 12 Zoltan Varga 2018-02-13 20:21:58 UTC
Comment 13 Brendan Zagaeski (Xamarin Team, assistant) 2018-02-14 19:37:28 UTC
## Bookkeeping note on regression status: not a recent regression

Based on the content of the fix, the problematic `g_assert()` was introduced by [1] near the beginning of 2017.  As an additional sanity-check of this information, I tested back a few versions with Xamarin.iOS and confirmed that the issue has been present for a few releases.

[1] https://github.com/mono/mono/commit/fb5bc8d4c539fe82b36f1cd3a3bc89236b39c4aa

BAD: Xamarin.iOS (d15-6:    5b1f7168)
BAD: Xamarin.iOS  (xcode9.2: db807ec9)
BAD: Xamarin.iOS  (d15-4-xi: 12e80e01)
Comment 14 Sebastien Pouliot 2018-02-19 15:13:42 UTC
PR was merged
Closing for QA verification