Bug 15719 - InvalidProgramException when executing async event handler that doesn't await
Summary: InvalidProgramException when executing async event handler that doesn't await
Status: RESOLVED FIXED
Alias: None
Product: Compilers
Classification: Mono
Component: C# ()
Version: unspecified
Hardware: PC Mac OS
: Normal normal
Target Milestone: ---
Assignee: Marek Safar
URL:
Depends on:
Blocks:
 
Reported: 2013-10-25 17:50 UTC by Frank A. Krueger
Modified: 2013-10-29 06:52 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Frank A. Krueger 2013-10-25 17:50:49 UTC
I got this exception today when I commented out an await line in an async event handler. This is running on the simulator.

System.InvalidProgramException: Invalid IL code in Calca.iOS.DocumentListController/<HandleTitleTap>c__async45:MoveNext (): IL_0013: ldloc.0   

  at System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Start[<HandleTitleTap>c__async45] (Calca.iOS.<HandleTitleTap>c__async45& stateMachine) [0x0001b] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Runtime.CompilerServices/AsyncVoidMethodBuilder.cs:106 
  at Calca.iOS.DocumentListController.<HandleTitleTap>m__15 (System.Object ss, System.EventArgs ee) [0x00000] in /Users/fak/Dropbox/Projects/Calca/Calca.iOS/DocumentListController.cs:226 
  at Praeclarum.UI.TextInputController+<HandleDone>c__async2C.MoveNext () [0x00198] in /Users/fak/Dropbox/Projects/Praeclarum/Praeclarum.iOS/UI/TextInputController.cs:90 


void HandleTitleTap (object sender, EventArgs e)
		{
			var name = DirectoryName;

			var c = new TextInputController () {
				Title = "Rename",
				InputText = name,
				ValidateFunc = n => AppDelegate.ValidateNewName (n, name),
			};

			var nc = new UINavigationController (c);
			nc.ModalPresentationStyle = UIModalPresentationStyle.FormSheet;

			c.Cancelled += (ss, ee) => {
				nc.DismissViewController (true, null);
			};
			c.Done += async (ss, ee) => {
				nc.DismissViewController (true, null);

				if (c.InputText != name) {
//                                      WHEN THIS IS COMMENTED OUT, bad IL is generated 
//					await Rename (c.InputText);
//
				}
			};

			PresentViewController (nc, true, null);
		}

TextInputController is just a UITableViewController that fires Cancelled and Done when UIBarButtonItems are clicked.

Here is the IL for MoveNext():

.method public final hidebysig newslot virtual 
	instance void MoveNext () cil managed 
{
	// Method begins at RVA 0x8614
	// Code size 69 (0x45)
	.maxstack 3

	IL_0000: ldarg.0
	IL_0001: ldfld int32 Calca.iOS.DocumentListController/'<HandleTitleTap>c__async45'::$PC
	IL_0006: ldarg.0
	IL_0007: ldc.i4.m1
	IL_0008: stfld int32 Calca.iOS.DocumentListController/'<HandleTitleTap>c__async45'::$PC
	IL_000d: brtrue IL_0044

	IL_0012: nop
	IL_0013: ldloc.0
	IL_0014: ldfld class [monotouch]MonoTouch.UIKit.UINavigationController Calca.iOS.DocumentListController/'<HandleTitleTap>c__AnonStorey44'::nc
	IL_0019: ldc.i4.1
	IL_001a: ldnull
	IL_001b: callvirt instance void [monotouch]MonoTouch.UIKit.UIViewController::DismissViewController(bool, class [monotouch]MonoTouch.Foundation.NSAction)
	IL_0020: ldloc.1
	IL_0021: callvirt instance string Praeclarum.UI.TextInputController::get_InputText()
	IL_0026: ldloc.0
	IL_0027: ldfld string Calca.iOS.DocumentListController/'<HandleTitleTap>c__AnonStorey44'::name
	IL_002c: call bool [mscorlib]System.String::op_Inequality(string, string)
	IL_0031: brfalse IL_0038

	IL_0036: nop
	IL_0037: nop

	IL_0038: nop
	IL_0039: ldarg.0
	IL_003a: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder Calca.iOS.DocumentListController/'<HandleTitleTap>c__async45'::$builder
	IL_003f: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::SetResult()

	IL_0044: ret
} 

There is no .locals.
Comment 1 Miguel de Icaza [MSFT] 2013-10-28 12:09:11 UTC
Frank,

Is this the actual full source code for this?

Because the method contains no "async" on the declaration, but it still produced a MoveNext method, which indicates that perhaps this is a code snippet?

We suspect maybe this was a caching issue, but wanted to confirm.
Comment 2 Frank A. Krueger 2013-10-28 12:25:11 UTC
This is the full code. Notice the async on the Done event handler:

    c.Done += async (ss, ee) => { ...
Comment 3 Marek Safar 2013-10-28 13:13:23 UTC
I can reproduce it with similar code

using System;

class Y
{
}

class X
{
	public event Action<int, string> E;

	void Foo ()
	{
		var nc = new Y ();

		E += async (arg1, arg2) => {
			nc = null;
		};
	}

	public static void Main ()
	{
	}
}
Comment 4 Marek Safar 2013-10-29 06:52:00 UTC
Fixed in master