[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