Bug 3693 - Crash using MKMapView with custom MKAnnotation
Summary: Crash using MKMapView with custom MKAnnotation
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: 5.2
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Sebastien Pouliot
URL:
Depends on:
Blocks:
 
Reported: 2012-02-29 16:47 UTC by Randy
Modified: 2012-03-08 20:47 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 FIXED

Description Randy 2012-02-29 16:47:36 UTC
This is similar to bug #2352 and the old novell bugzilla 686788. I get a crash on the device in a release build but can't determine the location since I just get my module name and an offset in the crash, not a function name.

Running in a debug build my setCoordinate function gets values with a high negative E value (like 1.231231231231E-311). This is probably caused by the runtime calling the function with a bad pointer.

This happened with code:

public class Annotation : MKAnnotation
{
  CLLocationCoordinate2D _coordinate;
  public override CLLocationCoordinate2D Coordinate {
    get { return _coordinate; }
    set { _coordinate = value; }
  }
...
}

If I add this explict export, the problem goes away:

[Export("_original_setCoordinate:")]
public void SetCoordinate (CLLocationCoordinate2D coord)
{
  Coordinate = coord;
}
Comment 1 Sebastien Pouliot 2012-02-29 17:12:46 UTC
I'll check that the #2352 fix did not get broken / reverted. 

Could you please attach a test case that shows the issue so we can be sure it's properly fixed ? thanks.
Comment 2 Sebastien Pouliot 2012-03-02 15:08:02 UTC
The original test case from https://bugzilla.novell.com/show_bug.cgi?id=686788 can be used to duplicate the issue - but it only occurs on devices (including debug builds) and not on the simulator. 

This is not related to the (managed) linker settings.

The original fix is still there so something else changed likely:
a) our registration; or
b) iOS internals (since it was a workaround in the first place). 

Re-exporting the selectors also triggers the previous fix (it's called in that case) so I'll look into (a) first.
Comment 3 Sebastien Pouliot 2012-03-02 17:15:16 UTC
Crash log (for future reference/comparison):

Stacktrace:

  at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
  at MonoTouch.UIKit.UIApplication.Main (string[]) [0x00000] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:43
  at AnnotationExample.Application.Main (string[]) [0x00000] in /Users/poupou/Downloads/AnnotationExample 2/AnnotationExample/Main.cs:14
  at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>

Native stacktrace:

	0   AnnotationExample                   0x01572ee0 mono_handle_native_sigsegv + 280
	1   AnnotationExample                   0x0155d4b0 mono_sigsegv_signal_handler + 268
	2   libsystem_c.dylib                   0x343ad7ed _sigtramp + 48
	3   AnnotationExample                   0x0159232c mono_arch_start_dyn_call + 588
	4   AnnotationExample                   0x0155f4b0 mono_jit_runtime_invoke + 1612
	5   AnnotationExample                   0x01607a2c mono_runtime_invoke + 128
	6   AnnotationExample                   0x01664110 monotouch_trampoline + 3228
	7   CoreFoundation                      0x34f347e4 __invoking___ + 68
	8   CoreFoundation                      0x34e8f7b1 -[NSInvocation invoke] + 160
	9   Foundation                          0x340a050f NSKVOForwardInvocation + 222
	10  CoreFoundation                      0x34f33a83 ___forwarding___ + 666
	11  CoreFoundation                      0x34e8e650 _CF_forwarding_prep_0 + 48
	12  MapKit                              0x370cceaf MKIntegerHash + 8126
	13  MapKit                              0x370a2445 MKZoomScaleForZoomLevelF + 2224
	14  MapKit                              0x370c2131 MKTilesRequireGoogleLegalNotices + 21912
	15  MapKit                              0x370c2207 MKTilesRequireGoogleLegalNotices + 22126
	16  UIKit                               0x36640aeb _UIGestureRecognizerSendActions + 106
	17  UIKit                               0x365d123d -[UIGestureRecognizer _updateGestureWithEvent:] + 304
	18  UIKit                               0x36801861 ___UIGestureRecognizerUpdate_block_invoke_0541 + 48
	19  UIKit                               0x3654d43d _UIGestureRecognizerApplyBlocksToArray + 176
	20  UIKit                               0x3654bf8b _UIGestureRecognizerUpdate + 898
	21  UIKit                               0x36558cd1 _UIGestureRecognizerUpdateGesturesFromSendEvent + 28
	22  UIKit                               0x36558b0f -[UIWindow _sendGesturesForEvent:] + 774
	23  UIKit                               0x365586dd -[UIWindow sendEvent:] + 88
	24  UIKit                               0x3653eb7d -[UIApplication sendEvent:] + 356
	25  UIKit                               0x3653e423 _UIApplicationHandleEvent + 5826
	26  GraphicsServices                    0x3185e22b PurpleEventCallback + 882
	27  CoreFoundation                      0x34f05523 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 38
	28  CoreFoundation                      0x34f054c5 __CFRunLoopDoSource1 + 140
	29  CoreFoundation                      0x34f04313 __CFRunLoopRun + 1370
	30  CoreFoundation                      0x34e874a5 CFRunLoopRunSpecific + 300
	31  CoreFoundation                      0x34e8736d CFRunLoopRunInMode + 104
	32  GraphicsServices                    0x3185d439 GSEventRunModal + 136
	33  UIKit                               0x3656d1bd UIApplicationMain + 1080
	34  AnnotationExample                   0x00b726e8 wrapper_managed_to_native_MonoTouch_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 240
	35  AnnotationExample                   0x00891d10 MonoTouch_UIKit_UIApplication_Main_string__ + 36
	36  AnnotationExample                   0x00003e50 AnnotationExample_Application_Main_string__ + 128
	37  AnnotationExample                   0x005c60a8 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
	38  AnnotationExample                   0x0155f4d0 mono_jit_runtime_invoke + 1644
	39  AnnotationExample                   0x01607a2c mono_runtime_invoke + 128
	40  AnnotationExample                   0x0160bd28 mono_runtime_exec_main + 436
	41  AnnotationExample                   0x016109a0 mono_runtime_run_main + 756
	42  AnnotationExample                   0x0156386c mono_jit_exec + 140
	43  AnnotationExample                   0x0155ba58 main + 2444
	44  AnnotationExample                   0x00003754 start + 52


It's also not part of registrar.m so I'm still looking into (a)
Comment 4 Sebastien Pouliot 2012-03-02 20:27:23 UTC
The previous stack trace was done using 'master' with an iPod Touch 4th gen (latest iOS).

But the same test case does not crash using 'master' (or the 5.2-series branch) with my iPad 1st gen (on iOS 5.0.1). However once the pin is moved it gets placed in the Gulf of Guinea (instead of where I dropped it).
Comment 5 Sebastien Pouliot 2012-03-05 11:38:44 UTC
My iPad behaves like my iPod Touch before d20df146069f2c8da7a11ce285bd51adcb6b28df

Things might look different between iOS versions but that's not the issue (just more confusion) since it occurs (Gulf of Guinea) about 1 out of 10 times on my iPod Touch.

Tried to change registration a bit (it's a special case) but I either get a "missing selector" (when registration does not work) or this crash (when registration works). Now thinking it's really trampoline related (re-assigning to Rolf).
Comment 6 Randy 2012-03-05 14:33:20 UTC
The 'Gulf of Guinea' effect is what I originally saw in a debug build on a device. If you check the coordinates being set they will have values like 1.231231231231E-311 which is effectively 0. Set a breakpoint on the "set { _coordinate = value; }" line.

On a release build on my device (iPod Touch), it crashes every time. 

The implictly created _original_setCoordinate function (without the fix) my be getting created with a wrong datatype. Then it casts to CLLocationCoordinate2D for the call to setCoordinate. I suspect it is pointing to invalid memory resulting the strange value in debug and crash in release due to a pointer issue.
Comment 7 Sebastien Pouliot 2012-03-05 15:45:51 UTC
It's a bit more complicated (and sadly undocumented) and could very well two different issues mixed together.

But to answer your previous comments the internal MonoTouch method is identical (code and signature) to the one in the test case (and yours from the original bug description) except it adds a [Preserve] attribute so the linker won't remove it (but it's not even present at runtime on devices).

In fact you can rename your SetCoordinate method and comment its code and it will still work (good coordinates and the Coordinate setter will be called too) since it's the MonoTouch internal code that gets called (not your method). E.g.

[Export("_original_setCoordinate:")]
public void SetCoordinateXXXXXXXXX (CLLocationCoordinate2D coord)
{
   // do not call Coordinate property!
}

This is why I suspected (and still think) it's something (partially?) related to selector registration (maybe I made a stupid mistake while trying alternatives and missing the right case?!?). OTOH the stack traces makes the trampolines a likely culprit too...
Comment 8 Sebastien Pouliot 2012-03-05 21:21:05 UTC
It's a registration issue after all (found it ;-)
Comment 9 Rolf Bjarne Kvinge [MSFT] 2012-03-08 20:47:05 UTC
Fixed in master (803df6b).

The first problem is that when ObjC registers the method _original_setCoordinate, the signature information is not included, so MonoTouch' dynamic invoke fails (it does not know how to marshal the parameters, effectively marshalling -2 parameters and therefore ending up dealing with random memory and/or crashes).

The second problem is that the _original_setCoordinate method MonoTouch provided wasn't always registered.

Now we redirect all calls from _original_setCoordinate to setCoordinate directly in our trampolines, which obviates the need for a managed _original_setCoordinate implementation (second problem fixed), and we'll use the signature information for setCoordinate (first problem fixed).