Bug 7019 - Unhandled exception
Summary: Unhandled exception
Status: RESOLVED INVALID
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: 5.4.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-09-09 13:36 UTC by Neal
Modified: 2012-09-10 10:20 UTC (History)
3 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 Developer Community or GitHub 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 INVALID

Description Neal 2012-09-09 13:36:01 UTC
Hello,

Code worked fine in 5.2.13, now broken in 5.4.

			public void TimeZone_Selected()
			{
				SaveSettings();
				if (MySettings.TimeZoneMode != 2)
					return;

				LoadingView lv = new LoadingView();
				lv.Show("Please Wait..."); //loading the list of time zones the first time can take a few seconds

				ThreadPool.QueueUserWorkItem(delegate
				{
					List<string> timezones = DateTimeUtils.GetTimeZoneNameList();

//extract the regions
					List<string> regions = new List<string>();
					foreach (string zone in timezones)
					{
						if (zone.Contains('/'))
						{
							string region = zone.Substring(0, zone.IndexOf('/'));
							if (!regions.Contains(region))
								regions.Add(region);
						}
					}

					var root = new RootElement("Time Zones");
					var section = new Section("Regions");

					foreach (string region in regions)
					{
						var regionElement = new RootElement(region);
						var subSection = new Section(region);

						var regionItems = from tz in timezones where tz.StartsWith(region) select tz;

						foreach (var item in regionItems)
						{
							string zone = item.Replace(region, ""); //remove the region part as that's the section title
							TimeZoneInfo tzi = DateTimeUtils.GetTimeZoneInfoById(item);
							var caption = string.Format("{0} ({1})", zone.TrimStart(new char[]{' ', '/'}), DateTimeUtils.GetUtcOffsetString(tzi));
							var sel = new StringElement(caption);
							sel.ShowRowHighlight = true;
							sel.ElementTapped += delegate(object sender, EventArgs e)
							{
								var el = (StringElement)sender;
								MySettings.CustomTimeZone = el.Tag;
								this.controller.NavigationController.DismissModalViewControllerAnimated(true);
							};
							sel.Tag = item;
							subSection.Add(sel);
						}

						regionElement.Add(subSection);
						section.Add(regionElement);

					}
					root.Add(section);
					//this is line #897
					var dvc = new DialogViewController(UITableViewStyle.Grouped, root, true, !MySettings.PreventUIRotate, Application.backColor);
					dvc.ModalTransitionStyle = UIModalTransitionStyle.FlipHorizontal;
					dvc.IsModal = true; //iOS 4 won't push the secondary listing since the initial view is modal

					BeginInvokeOnMainThread(delegate
					{
						lv.Hide();
						this.controller.NavigationController.PresentModalViewController(dvc, true);
					}
					);
				}
				);
			}

---

Unhandled Exception:
0   LogbookPro                          0x000988f2 mono_handle_exception_internal_first_pass + 3058
1   LogbookPro                          0x00099fd2 mono_handle_exception_internal + 1602
2   LogbookPro                          0x0009ab1f mono_handle_exception + 47
3   LogbookPro                          0x000dda82 mono_x86_throw_exception + 306
4   ???                                 0x09a3df8f 0x0 + 161734543
at MonoTouch.UIKit.UITableViewController..ctor (MonoTouch.UIKit.UITableViewStyle) [0x00010] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UITableViewController.g.cs:96
at NCSoftware.Dialog.DialogViewController..ctor (MonoTouch.UIKit.UITableViewStyle,NCSoftware.Dialog.RootElement,bool,bool,MonoTouch.UIKit.UIColor) <IL 0x00058, 0x0009c>
at LogbookPro.RootViewController/DataSource/<TimeZone_Selected>c__AnonStorey1D.<>m__5E (object) [0x001e6] in /Users/neal007/Dev/Logbook Pro/Logbook_Pro/XIBs/RootViewController.xib.cs:897
at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <IL 0x0001e, 0x00045>
9   LogbookPro                          0x00014032 mono_jit_runtime_invoke + 722
10  LogbookPro                          0x001758ce mono_runtime_invoke + 126
11  LogbookPro                          0x00175a3c mono_runtime_delegate_invoke + 140
12  LogbookPro                          0x001ab374 async_invoke_thread + 1940
13  LogbookPro                          0x001b1126 start_wrapper + 422
14  LogbookPro                          0x001e30ea thread_start_routine + 154
15  LogbookPro                          0x0020a4dd GC_start_routine + 93
16  libsystem_c.dylib                   0x95dfa557 _pthread_start + 344
17  libsystem_c.dylib                   0x95de4cee thread_start + 34
Comment 1 Neal 2012-09-09 13:41:21 UTC
Happening in another code section as well:

//starts at line #192

		private void DoSearch()
		{
			infoTextEdit.Text = "Retrieving weather, please wait...";
			searchButton.Enabled = false;
			HideKeyboard();
			string weatherResult = string.Format("Unable to retrieve weather for {0}", icaoTextBox.Text);
			Helper.ToggleNetworkStatusIndicator(true);
			ThreadPool.QueueUserWorkItem(delegate
			{
				var icaoList = icaoTextBox.Text.ToListFromCommaDelim(true);
				var isConnected = Services.Main.IsConnected;
				if (isConnected)
					weatherResult = Services.Weather.GetWeather(icaoList);
				BeginInvokeOnMainThread(delegate
				{
					Helper.ToggleNetworkStatusIndicator(false);
					if (!isConnected)
					{
						Alerts.ShowNoInternetWarning();
					}
					else
					{
						Application.WeatherData += weatherResult;
					}
					infoTextEdit.Text = Application.WeatherData;
					ButtonStatus();
				}
				);
			}
			);	
		}

---

Unhandled Exception:
0   LogbookPro                          0x000988f2 mono_handle_exception_internal_first_pass + 3058
1   LogbookPro                          0x00099fd2 mono_handle_exception_internal + 1602
2   LogbookPro                          0x0009ab1f mono_handle_exception + 47
3   LogbookPro                          0x000dda82 mono_x86_throw_exception + 306
4   ???                                 0x09a3df8f 0x0 + 161734543
at MonoTouch.UIKit.UITextField.get_Text () [0x00000] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UITextField.g.cs:689
at LogbookPro.WeatherViewController/<DoSearch>c__AnonStorey24.<>m__72 (object) [0x0000d] in /Users/neal007/Dev/Logbook Pro/Logbook_Pro/XIBs/WeatherViewController.cs:201
at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <IL 0x0001e, 0x00045>
8   LogbookPro                          0x00014032 mono_jit_runtime_invoke + 722
9   LogbookPro                          0x001758ce mono_runtime_invoke + 126
10  LogbookPro                          0x00175a3c mono_runtime_delegate_invoke + 140
11  LogbookPro                          0x001ab374 async_invoke_thread + 1940
12  LogbookPro                          0x001b1126 start_wrapper + 422
13  LogbookPro                          0x001e30ea thread_start_routine + 154
14  LogbookPro                          0x0020a4dd GC_start_routine + 93
15  libsystem_c.dylib                   0x95dfa557 _pthread_start + 344
16  libsystem_c.dylib                   0x95de4cee thread_start + 34
Comment 2 Sebastien Pouliot 2012-09-09 16:34:05 UTC
                    //this is line #897
                    var dvc = new
DialogViewController(UITableViewStyle.Grouped, root, true,

^ by calling this you're using UIKit from another (not the main) thread. Apple's UIKit is _not_ thread safe and doing so causes all kind of weird issues (usually a bit later when it's hard to diagnose).

In MonoTouch 5.4 the default (in DEBUG) is to throw an exception [1] when this occurs (so you can fix such cases before hitting weird bugs).

Did you execute this under the (MD) debugger ? it should have popped up the exception that would have made the situation clearer than the crash you're getting.


[1] http://spouliot.wordpress.com/2012/03/02/linker-vs-bindings-and-ui-thread-checks/
Comment 3 Neal 2012-09-09 20:15:07 UTC
I am running in DEBUG in the iOS Simulator.  All I got was the ugly exception.  What about the code in comment #1, another method I'm having the same problem.  It seems to be any use of Threadpool.QueueWorkerItem but not sure.
Comment 4 Miguel de Icaza [MSFT] 2012-09-09 22:52:50 UTC
Neal,

Likely this is also wrong:


                var icaoList = icaoTextBox.Text.ToListFromCommaDelim(true);

I am guess here that icaoTextBox is a UITextField, and you are trying to access the "Text" property from a background thread.

This is a bug in your code, and it could eventually crash under the wrong conditions.

You can disable this new feature that checks invalid background uses of UIKit by changing this value:

http://iosapi.xamarin.com/?link=F%3aMonoTouch.UIKit.UIApplication.CheckForIllegalCrossThreadCalls
Comment 5 Neal 2012-09-10 10:20:47 UTC
Thanks Miguel, you're right (again).  I wonder though if this is too aggressive and should be a compiler warning instead of a nasty exception that scares the heck out of a programmer?  I've never had a problem with these calls and while it may affect "debugging" does it affect the running of the application?  I haven't seen it.  I'm not asking the UI to update such as in the case where I am retrieving a value from a UITextField.  True, it's accessing the main UI thread and that can easily be corrected by putting that value in a variable prior to going async.  Just like building a MonoTouch.Dialog view (or any view) in the background, it's not pushing the view to display, it's just building the view. Is that really wrong or is it wrong when trying to update a view from a background thread?

You're making me program better so that's good, but I have mixed feelings on this.  Thanks for the assistance and even more so the outstanding work since forming Xamarin - superb job!!!