[Mono-osx] HELP! Trouble managing lifetime of NSPanel and other windows

Steve Orth steven.orth at ni.com
Mon Mar 26 16:23:50 UTC 2012


First, a confession: I'm new to the OS X development world's modern APIs 
-- my experience lies mainly in the ancient era (pre OS X/Carbon). I'm now 
working on a UI implementation that's NSWindow / NSView based for a large 
application and have jumped into this in MonoMac / MonoDevelop. So I'm not 
well-versed on the Objective-C layer either - really just walked the plank 
and trying to tread water as I learn this. :-)

My situation is this:

In a simple test application, I am trying to get a feel for managing 
window lifetimes by simply having File>>New create a new NSPanel. I've got 
a couple options to dump the app's window list and also a "debug list" of 
weak references to the NSPanels to see what happens w.r.t. the C# wrapper 
object lifetimes. I've tried w/ and w/o creating a NSWindowController, but 
that seems to have no effect w.r.t. crashing.

I've set the NSPanel's ReleasedWhenClosed to true. I also maintain a 
dictionary of NSPanel, NSWindowController pairs so the C# GC doesn't start 
tossing things out on me. In a nutshell, here's the "important" code:

        public static void NewPanel()
        {
            NSPanel p = new NSPanel();
            _panels[p] = new NSWindowController(p); // stash a reference 
(or two) so GC won't toss the NSPanel out
            p.StyleMask |= NSWindowStyle.Resizable | (NSWindowStyle)16 /* 
NSUtilityWindowMask */;
            p.FloatingPanel = true;
            p.Title = "Panel " + (++_panelNumber);
            p.ReleasedWhenClosed = true;
            p.WillClose += HandlePanelWillClose;

            _panelTracker[p.Title] = new WeakReference(p);

            p.IsVisible = true;
            System.Console.WriteLine(p.Title + " [" + 
p.Handle.ToString("X") + "]");
        }

        private static void HandlePanelWillClose (object sender, EventArgs 
e)
        {
            NSPanel p = (NSPanel)((NSNotification)sender).Object;
            bool removed = _panels.Remove(p);
            System.Console.WriteLine("Closing " + p.Title + "[" + 
p.Handle.ToString("X") + "]; removed: " + removed + ", num in list: " + 
_panels.Count);
            DumpWeakReferenceList();
        }

        public static void DumpWeakReferenceList()
        {
            System.GC.Collect();
            System.Console.WriteLine("|---- Weak References List ----|");
            foreach (KeyValuePair<string, WeakReference> pair in 
_panelTracker)
            {
                System.Console.WriteLine(pair.Key + " -> " + 
pair.Value.IsAlive);
            }
            System.Console.WriteLine("");
        }

        public static void DumpAppWindowList()
        {
            System.GC.Collect();
            System.Console.WriteLine("|---- Window List ----|");
            foreach (NSWindow w in 
NSApplication.SharedApplication.Windows)
            {
                System.Console.WriteLine(" > " + w.Title + " [" + 
w.Handle.ToString("X") + "]");
            }
            System.Console.WriteLine("");
        }

At some point, inevitably, the app crashes like this:

  at (wrapper managed-to-native) 
MonoMac.ObjCRuntime.Messaging.void_objc_msgSend (intptr,intptr) <IL 
0x00024, 0xffffffff>
  at MonoMac.Foundation.NSObject/MonoMac_Disposer.Drain 
(MonoMac.Foundation.NSObject) [0x0007b] in 
/cvs/monomac/src/Foundation/NSObject.cs:360
  at (wrapper dynamic-method) 
object.[MonoMac.Foundation.NSObject+MonoMac_Disposer.Void 
Drain(MonoMac.Foundation.NSObject)] 
(MonoMac.Foundation.NSObject,MonoMac.ObjCRuntime.Selector,MonoMac.Foundation.NSObject) 
<IL 0x00011, 0x0004b>
  at (wrapper native-to-managed) 
object.[MonoMac.Foundation.NSObject+MonoMac_Disposer.Void 
Drain(MonoMac.Foundation.NSObject)] 
(MonoMac.Foundation.NSObject,MonoMac.ObjCRuntime.Selector,MonoMac.Foundation.NSObject) 
<IL 0x000b6, 0xffffffff>
  at (wrapper managed-to-native) 
MonoMac.AppKit.NSApplication.NSApplicationMain (int,string[]) <IL 0x0009d, 
0xffffffff>
  at MonoMac.AppKit.NSApplication.Main (string[]) [0x00000] in 
/cvs/monomac/src/AppKit/NSApplication.cs:74
  at SimpleMonoApp.MainClass.Main (string[]) [0x00005] in 
/Users/steveno/projects/NextGen/R2/PlatformFramework/Dev/SimpleMonoApp/Main.cs:14
  at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object 
(object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>

Native stacktrace:

        0   SimpleMonoApp                       0x00094efc 
mono_handle_native_sigsegv + 284
        1   SimpleMonoApp                       0x00004fe8 
mono_sigsegv_signal_handler + 248
        2   libsystem_c.dylib                   0x944bc59b _sigtramp + 43
        3   ???                                 0xffffffff 0x0 + 
4294967295
        4   ???                                 0x05af3024 0x0 + 95367204
        5   ???                                 0x01f59144 0x0 + 32870724
        6   ???                                 0x01f4c43c 0x0 + 32818236
        7   CoreFoundation                      0x946a6de1 -[NSObject 
performSelector:withObject:] + 65
        8   Foundation                          0x9c4bde40 
__NSThreadPerformPerform + 503
        9   CoreFoundation                      0x9461e3df 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
        10  CoreFoundation                      0x9461dd96 
__CFRunLoopDoSources0 + 246
        11  CoreFoundation                      0x94647c68 __CFRunLoopRun 
+ 1112
        12  CoreFoundation                      0x9464747c 
CFRunLoopRunSpecific + 332
        13  CoreFoundation                      0x94647328 
CFRunLoopRunInMode + 120
        14  AppKit                              0x918f720e 
_NSUnhighlightCarbonMenu + 199
        15  AppKit                              0x91900ae5 
-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 204
        16  AppKit                              0x9190014d -[NSMenu 
_performActionWithHighlightingForItemAtIndex:sendAccessibilityNotification:] 
+ 79
        17  AppKit                              0x919000f9 -[NSMenu 
_performActionWithHighlightingForItemAtIndex:] + 48
        18  AppKit                              0x91879933 -[NSMenu 
performKeyEquivalent:] + 306
        19  AppKit                              0x918783a2 -[NSApplication 
_handleKeyEquivalent:] + 594
        20  AppKit                              0x9176c4bf -[NSApplication 
sendEvent:] + 5772
        21  AppKit                              0x916fd6d5 -[NSApplication 
run] + 1007
        22  AppKit                              0x91991261 
NSApplicationMain + 1054
        23  ???                                 0x04103e6e 0x0 + 68173422
        24  ???                                 0x04103c6c 0x0 + 68172908
        25  ???                                 0x004a7ff8 0x0 + 4882424
        26  ???                                 0x004a8156 0x0 + 4882774
        27  SimpleMonoApp                       0x0000d282 
mono_jit_runtime_invoke + 722
        28  SimpleMonoApp                       0x001a436a 
mono_runtime_invoke + 170
        29  SimpleMonoApp                       0x001a6f01 
mono_runtime_exec_main + 705
        30  SimpleMonoApp                       0x001a6111 
mono_runtime_run_main + 929
        31  SimpleMonoApp                       0x00069995 mono_jit_exec + 
149
        32  SimpleMonoApp                       0x0006bf13 mono_main + 
9587
        33  SimpleMonoApp                       0x00002299 main + 441
        34  SimpleMonoApp                       0x000020a6 start + 54

Debug info from gdb:


=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

In the larger scope of things, those "NSPanels" aren't going to just be a 
finite set of utility windows, so keeping them around "forever" isn't an 
option. It may well be that I'm doing something grossly incorrect, but in 
this simple app, it should be easier to spot.

Thanks for any insights / advice!

-steve
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ximian.com/pipermail/mono-osx/attachments/20120326/c834e19c/attachment.html>


More information about the Mono-osx mailing list