Crash when creating MenuItem in code (MonoMac)

290 Views Asked by At

I am trying to add some menu items into a submenu dynamically during runtime. I can add the NSMenuItem fine and it shows up. But if I try to add an event handler, either directly as an argument to the constructor, or by assigning it to the Activated event, I get a crash. The menu and submenu is created in Xcode. I just add/remove items in one specific submenu during runtime.

The crash occurs when the submenu is drawn. I right-click, move my mouse over the context menu until I come to the item under which my dynamic submenu resides, and crash!

The crash report is quite long but here's the part that I think is most relevant:

Thread 1 (process 6706):
#0  0x94f73095 in __wait4 ()
#1  0x9928699a in waitpid$UNIX2003 ()
#2  0x004a7d22 in mono_handle_native_sigsegv (signal=11, ctx=0xf6fe0) at mini-exceptions.c:2344
#3  0x004f7645 in mono_arch_handle_altstack_exception (sigctx=0xf6fe0, fault_addr=0xc8080824, stack_ovf=0) at exceptions-x86.c:1135
#4  0x00404061 in mono_sigsegv_signal_handler (_dummy=11, info=0xf6fa0, context=0xf6fe0) at mini.c:6556
#5  <signal handler called>
#6  0x98a83a8b in objc_msgSend ()
#7  0xbfffd920 in ?? ()
#8  0x9730c963 in -[NSCarbonMenuImpl _carbonUpdateStatusEvent:handlerCallRef:] ()
#9  0x973086ee in NSSLMMenuEventHandler ()
#10 0x908f79bb in _InvokeEventHandlerUPP ()
#11 0x9077f394 in DispatchEventToHandlers ()
#12 0x9077e780 in SendEventToEventTargetInternal ()
#13 0x90792655 in SendEventToEventTarget ()
#14 0x908f786a in SendHICommandEvent ()
#15 0x907535f0 in UpdateHICommandStatusWithCachedEvent ()
#16 0x9077abe2 in HIApplication::EventHandler ()
#17 0x908f79bb in _InvokeEventHandlerUPP ()
#18 0x9077f394 in DispatchEventToHandlers ()
#19 0x9077e780 in SendEventToEventTargetInternal ()
#20 0x90792655 in SendEventToEventTarget ()
#21 0x90943054 in SendMenuOpening ()
#22 0x90752dfd in DrawTheMenu ()
#23 0x90945779 in OpenSubmenu ()
#24 0x90752427 in TrackMenuCommon ()
#25 0x9094490d in PopUpMenuSelectCore ()
#26 0x909441e2 in _HandlePopUpMenuSelection7 ()
#27 0x97398295 in _NSSLMPopUpCarbonMenu3 ()
#28 0x973971b1 in -[NSCarbonMenuImpl _popUpContextMenu:withEvent:forView:withFont:] ()
#29 0x97515063 in -[NSMenu _popUpContextMenu:withEvent:forView:withFont:] ()
#30 0x97514f56 in -[NSMenu _popUpContextMenu:withEvent:forView:] ()
#31 0x97515390 in -[NSMenu _popUpMenuWithEvent:forView:] ()
#32 0x9771af45 in -[NSView rightMouseDown:] ()
#33 0x973ed635 in -[NSControl _rightMouseUpOrDown:] ()
#34 0x973ed69f in -[NSControl rightMouseDown:] ()
#35 0x971c8af1 in -[NSWindow sendEvent:] ()
#36 0x971c390f in -[NSApplication sendEvent:] ()
#37 0x970dd62c in -[NSApplication run] ()
#38 0x970805f6 in NSApplicationMain ()
#39 0x06de146b in ?? ()
#40 0x06de1290 in ?? ()
#41 0x000befe4 in ?? ()
#42 0x000bf12f in ?? ()
#43 0x0040dc05 in mono_jit_runtime_invoke (method=0x9e8c1c, obj=0x0, params=0xbffff468, exc=0x0) at mini.c:6438
#44 0x005c49ae in mono_runtime_invoke (method=0x9e8c1c, obj=0x0, params=0xbffff468, exc=0x0) at object.c:2827
#45 0x005c8dc4 in mono_runtime_exec_main (method=0x9e8c1c, args=0xe7f30, exc=0x0) at object.c:4054
#46 0x005c9135 in mono_runtime_run_main (method=0x9e8c1c, argc=0, argv=0x168d18, exc=0x0) at object.c:3678
#47 0x00478685 in mono_jit_exec (domain=0x94e00, assembly=0x1833b0, argc=2, argv=0x168d18) at driver.c:955
#48 0x0047abbf in mono_main (argc=4, argv=0x168d10) at driver.c:1014
#49 0x0000308f in main ()

I am running Xamarin Studio 4.0.12, Mono 3.2.0, Xcode 4.6.3, Xamarin.Mac 1.4.8, OS X 10.8.4

2

There are 2 best solutions below

0
On

I'm hoping our experience could shed some light. Although without any code it's rather difficult.

Xamarin.Mac does a fantastic job abstracting this stuff from c# types. However one thing that can't be avoided is the VERY different way each OS (and the windowing systems in particular) time painting events and resource retention.

In particular with the Cocoa Controller style of windowing, there's a far greater risk of items that are expected to always be referenced in memory to have already been cleaned up, as Cocoa seems far happier switching Windows/Controllers and re-hydrating again.

Tl;DR

  1. Keep a modular reference to your menuItems - store them in a field on the controller. Otherwise they could be collected.
  2. Before performing repainting, ensure you've no circular references (with Cocoa's habit of defining behaviour in Delegates belonging to objects this is much easier than Windows)
  3. Removing menu items must be from the end to the start (remember counts will reduce as we remove)

We have generally found such mysterious crashes to be due to disappearing controls and or delegates referring to objects that have a reference to the delegate.

I'm sure with more code I can help more!

CHeers ian

0
On

I think I've actually found the problem. It seems the crashes disappear completely when I remove all code which touch the Properties.Settings stuff. This class inherits from System.Configuration.ApplicationSettingsBase. You can see the whole class here: https://code.google.com/p/yet-another-music-application/source/browse/trunk/Player/Core/Properties/Settings.Designer.cs?r=1838

It is probably my fault, since I have taken this simple method of persistent storage and run with it farther than what is intended. So my solution is to move over to SQLite instead which will probably serve me in more ways than just prevent these crashes.

In any case, it seems that the crashes are somewhat random. It could be because the access to this class is mostly done from various threads.

In any case, I'm pretty sure the combination is lethal. Removing either one (event handlers or ApplicationSettingsBase) removes the crashes.