Use of NSAlert is crashing regularly

KeithBoyntonKeithBoynton GBMember ✭✭
edited December 2013 in Xamarin.Mac

The following use of an NSAlert is resulting in regular crashing after recent updates to OSX, Xcode, XamarinMac and Xamarin Studio...

NSAlert oAlert = new NSAlert(); // Set the buttons oAlert.InvokeOnMainThread(delegate { oAlert.AddButton("Yes"); oAlert.AddButton("No"); }); // Show the message box and capture oAlert.MessageText = "Title"; oAlert.InformativeText = "The message"; oAlert.AlertStyle = NSAlertStyle.Informational; var responseAlert = oAlert.RunModal(); // // <---- Crashes here sometimes (after choosing an option) // if (responseAlert == 1000) { // Do something }

It doesn't crash on every display but very regularly!

Any help would be greatly appreciated.

Posts

  • MikeCodesDotNetMikeCodesDotNet GBXamarin Team Xamurai

    Hi Keith,

    I created a very basic sample App with your code and cannot reproduce the issue (I showed the alert 50 times and stopped).

    Could you give some details on the crash? Do you get an exception?

    All the best,
    Mike

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Hi Mike,

    Thanks for your quick response.. details (file) attached and my env setup is below:

    OSX 10.9 (13A603) Xcode 5.0.2 (5A3005)

    === Xamarin Studio ===

    Version 4.0.13 (build 38) Installation UUID: ae08c50a-24cf-4f39-a9b3-1eb017881e50 Runtime: Mono 3.2.5 ((no/964e8f0) GTK+ 2.24.20 theme: Raleigh GTK# (2.12.0.0) Package version: 302050000

    === Apple Developer Tools ===

    Xcode 5.0.2 (3335.32) Build 5A3005

    === Xamarin.iOS ===

    Not Installed

    === Xamarin.Mac ===

    Xamarin.Mac: 1.6.19

    === Xamarin.Android ===

    Not Installed

    === Build Information ===

    Release ID: 400130038 Git revision: 07afec667f7be5d0ee511eb7115bbac6377fbae8 Build date: 2013-09-24 08:53:29+0000 Xamarin addins: 61140345a5b109633a94409edcbc7a4c19a425c6

    === Operating System ===

    Mac OS X 10.9.0 Darwin Flares-Mac-mini.local 13.0.0 Darwin Kernel Version 13.0.0 Thu Sep 19 22:22:27 PDT 2013 root:xnu-2422.1.72~6/RELEASE_X86_64 x86_64

  • NikolayIvanetsNikolayIvanets USMember ✭✭

    @KeithBoynton, seems, you show the alert not from main thread? Try this code:

    InvokeOnMainThread(() => {
        NSAlert oAlert = new NSAlert();
    
        // Set the buttons
        oAlert.AddButton("Yes");
        oAlert.AddButton("No");
    
        // Show the message box and capture
        oAlert.MessageText = "Title";
        oAlert.InformativeText = "The message";
        oAlert.AlertStyle = NSAlertStyle.Informational;
        var responseAlert = oAlert.RunModal();
    
        if (responseAlert == 1000) {
            // Do something
        }
    });
    
  • KeithBoyntonKeithBoynton GBMember ✭✭

    Thanks for your suggestion Nikolay I did wonder if enough of the code was within the "InvokeOnMainThread". I'm not near my Mac environment today but will try that later.

    The code has been working fine but started to crash on a recent update.

    I'll post progress back here afterwards...

  • cleardemoncleardemon USMember

    It might be possible that the value of oAlert is being disposed by the GC before control returns from the modal runloop.

    I had a similar problem and solved it by keeping a reference to the NSAlert object in something that wasn't as volatile as the method (such as the class). Something like:

    NSAlert _alert;
    
    void MyMethod()
    {
       _alert = new NSAlert();
       // ...
       var result = _alert.RunModal();
       // ...
    }
    
  • KeithBoyntonKeithBoynton GBMember ✭✭

    I tried both of these suggestions and unfortunately no joy.

    Thanks for the suggestions guys, scoping the alert at class level improved things slightly but eventually (on the third alert) it crashed.

    The alert is wrapped in a method in a helper class which can be called either from the main thread or another background thread.

    The funny thing is this very code has been working just fine until recent updates to Xamarin Mac, Xamarin Studio, Xcode and OSX.

    There is a version on the AppStore of the very same codebase which is working just fine, there is something new in these builds that's now not working. Hmmm.

    Here's the full code that's still crashing (albeit less often)....

    // Show a message and get a response back from the user, int code public static MessageResult ShowMessageAndGetResponse(String title, String message, MessageType type, MessageButtons buttons) { int responseAlert = 0; var oAlert = new NSAlert(); oAlert.InvokeOnMainThread(() => { // Set the type NSAlertStyle style = NSAlertStyle.Informational; // Set the buttons oAlert.AddButton("No"); oAlert.AddButton("Yes"); // Show the message box and capture oAlert.MessageText = title; oAlert.InformativeText = message; oAlert.AlertStyle = style; responseAlert = oAlert.RunModal(); }); // Transform the result (so it's consistent regardless of GUI implementation) switch (buttons) { case MessageButtons.YesNo: return responseAlert == 1000 ? MessageResult.No : MessageResult.Yes; case MessageButtons.YesNoCancel: switch (responseAlert) { case 1000: return MessageResult.Cancel; case 1001: return MessageResult.No; case 1002: return MessageResult.Yes; default: return MessageResult.No; } case MessageButtons.Ok: return MessageResult.Ok; case MessageButtons.OkCancel: return responseAlert == 1000 ? MessageResult.Cancel : MessageResult.Ok; default: return MessageResult.No; } }

  • ta.speot.ista.speot.is AUMember
    edited December 2013

    I have noticed my application freezing up at random times after some recent updates. In this past, random freezing has been my fault (accessing NSApplication from a non-UI thread). But Xamarin did add a bunch of checks to some NS* classes which caught instances of that problem.

    It's also happened when some object has gone out of scope but the native runtime has a handle to it.

    To avoid, I have this before NSApplication.Init and NSApplication.Main:

    #if DEBUG
                ThreadPool.QueueUserWorkItem (v =>
                {
            for (;; GC.Collect(GC.MaxGeneration))
                        Thread.Sleep(100);
                });
    #endif
    

    Which should aggressively crash the application if I "lose" an object that the native runtime relies on (i.e. make sure the GC runs, because if it doesn't the object I've "lost" won't be collected and the app might still run okay). But from time to time the application crashes and the stack trace looks like:

    Stacktrace:
    
      at <unknown> <0xffffffff>
      at (wrapper managed-to-native) System.GC.InternalCollect (int) <0xffffffff>
      at System.GC.Collect (int) <0x00017>
      at XXXXXXXX.Client.OSX.Program.<Main>m__0 (object) <0x00037>
      at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff>
    

    So it would appear to crash in the act of GC'ing.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    @MichaelJames Can we get any engineering response on this please, I can only see this as a bug within Xamarin.Mac at this time as I've investigated all options I can think of.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    @MichaelJames This has been raised as a bug: https://bugzilla.xamarin.com/show_bug.cgi?id=17118

    What sort of timescale can I expect this to get looked at, as it's a huge showstopper for my Mac release stream?

  • VivekJhaveriVivekJhaveri USMember

    I've been following this thread as I am also getting these random crashes since upgrading to the latest Xamarin.Mac.

    The Application output has a long stream of lines containing "quit" and "^D" and a long trace, which includes:

    quit
    quit
    quit
    quit
    quit
    quit
    quit
    quit^D
    qu* thread #1: tid = 0x7287aa, 0x93672095 libsystem_kernel.dylib`__wait4 + 5, queue = 'com.apple.main-thread, stop reason = signal SIGSTOP
    frame #0: 0x93672095 libsystem_kernel.dylib`__wait4 + 5
    frame #1: 0x957c098a libsystem_c.dylib`waitpid$UNIX2003 + 69
    frame #2: 0x021a8482 libmono-2.0.dylib`mono_handle_native_sigsegv(signal=11, ctx=0x000fffe0) + 498 at mini-exceptions.c:2344
    frame #3: 0x021f87a5 libmono-2.0.dylib`mono_arch_handle_altstack_exception(sigctx=0x000fffe0, fault_addr=0x000000b6, stack_ovf=0) + 149 at exceptions-x86.c:1167
    frame #4: 0x021034e1 libmono-2.0.dylib`mono_sigsegv_signal_handler(_dummy=10, info=0x000fffa0, context=0x000fffe0) + 369 at mini.c:6591
    

    Has there been any progress on this issue? How does one begin to even start debugging it?

    I have a business license for Xamarin.Mac.
    Thanks.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Hi @VivekJhaveri I managed to get a bug filed for this at: https://bugzilla.xamarin.com/show_bug.cgi?id=17118

    But unfortunately I only have an indie license so it doesn't seem to be getting the attention I'd hoped for. Maybe as you have a business license you may be able to give it some traction :)

    It's a complete showstopper for me and is now damaging my progress considerably, hopefully that's not happening for you yet!

  • NikolayIvanetsNikolayIvanets USMember ✭✭

    Could someone share simple project, demonstrated the issue?

  • KeithBoyntonKeithBoynton GBMember ✭✭

    I will certainly try to put something together over the new few days, unless @VivekJhaveri has something to hand already?

  • VivekJhaveriVivekJhaveri USMember

    I am unable to isolate the problem for the very reason stated - the stack trace makes it extremely hard to debug. For starters, what is causing the long sequence of "quit" and "^D" in the output?

    Any tips at this point are appreciated.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    I've done some more work around this and I notice something else, it's actually crashing when called off the main thread already. So no invoke on main thread needed.

    I can click the alert numerous times and intermittently it crashes.

    I'm not convinced this is thread related, any ideas?

    Calling code in the MainGUIController.cs
    // Empty the playlist public void EmptyPlaylistToolStripMenuItemClick() { if (GUIHelper.ShowMessageAndGetResponse("Confirm clear all", "Are you sure you want to empty your playlist?", MessageType.Question, MessageButtons.YesNo) == MessageResult.Yes) { if (_applicationController.ClearPlaylist()) { RebuildGUIPlaylist(); } } }

    Method in GUIHelper.cs
    // Show a message and get a response back from the user, int code public static MessageResult ShowMessageAndGetResponse(String title, String message, MessageType type, MessageButtons buttons) { NSAlert _alert = new NSAlert(); SetMessageBoxButtons(buttons,_alert); _alert.MessageText = title; _alert.InformativeText = message; _alert.AlertStyle = SetMessageBoxType(type); int responseAlert = _alert.RunModal(); // Transform the result (so it's consistent regardless of GUI implementation) switch (buttons) { case MessageButtons.YesNo: return responseAlert == CODE_FIRST_BUTTON ? MessageResult.No : MessageResult.Yes; case MessageButtons.YesNoCancel: switch (responseAlert) { case CODE_FIRST_BUTTON: return MessageResult.Cancel; case CODE_SECOND_BUTTON: return MessageResult.No; case CODE_THIRD_BUTTON: return MessageResult.Yes; default: throw new NotImplementedException(); } case MessageButtons.Ok: return MessageResult.Ok; case MessageButtons.OkCancel: return responseAlert == CODE_FIRST_BUTTON ? MessageResult.Cancel : MessageResult.Ok; default: throw new NotImplementedException(); } }

  • GarethBrownGarethBrown GBMember ✭✭
    edited February 2014

    Have you tried to scale it back to a very simple alert? I'm guessing so, but have to ask.

    public void EmptyPlaylistToolStripMenuItemClick() { var alert = new NSAlert () { MessageText = "Test", InformativeText = "Testing" }; var responseAlert = alert.RunModal(); if (responseAlert == 1000) { } }

    I can't tell you how much time I've spent tracking down a bug, only to find it was something so simple.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Hi Gareth,

    Thanks for your response, I have tried exactly that. I've just pasted that exact code in and it crashes too.

  • MikeCodesDotNetMikeCodesDotNet GBXamarin Team Xamurai

    Hi Keith,

    Can you confirm that the following sample doesn't work for you?

    https://www.dropbox.com/s/2t5odam8dof04xc/Alert.zip

    All the best,
    Mike

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Hi Mike,

    Your sample works just fine, and funnily enough my sample in the crashing app works fine at the mo too!

    However, I've just done some further digging in the code and I've noticed some InvokeOnMainThread calls that are unnecessary as it's already running on the main thread. If I toggle using the invoke and not using it. I can't get it to crash when it isn't used but it crashes very regularly when it is used. It seems that this is the culprit.

    Is there no way of selectively invoking on the main thread like in .net "InvokeRequired" ??

  • KeithBoyntonKeithBoynton GBMember ✭✭

    I'm moving into theory territory here but this very same code which is now crashing in Mavericks has been around for a while and wasn't crashing before Mavericks. So, it's certainly possible that Mavericks is more sensitive to receiving unnecessary InvokeOnMainThread calls when the code is already on the main thread.

    So I'm guessing that if InvokeOnMainThread can be called conditionally only when needed we may have a resolution here!

  • KeithBoyntonKeithBoynton GBMember ✭✭

    So after some further investigation I tried wrapping the InvokeOnMainThread calls on the following condition:

    if (!NSThread.Current.IsMainThread) { InvokeOnMainThread.... } else { JustDoIt... }

    But that didn't seem to work!

  • KeithBoyntonKeithBoynton GBMember ✭✭

    It seems this was a Xamarin bug after all, it's fixed in the latest version in the beta channel.

    Grrr, wasted a lot of time on this!

  • VivekJhaveriVivekJhaveri USMember
    edited March 2014

    Keith, thanks for the update. Can you provide any details about the issue?

    Xamarin folks - when will this be in a stable build - it is really a blocking issue.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Hi Vivek, I'm afraid I can't help, the issue mysteriously went away with a Xamarin.Mac update and no code changes on our side but I can't get any information out of Xamarin as to what is likely to have fixed it.

    There seems to be all sorts of problems with Xamarin.Mac since Mavericks but I'm having a really hard time getting to the bottom of it to work out whether it's code or Xamarin library related.

    I'm trying to work with Xamarin support on it but it's difficult because I'm not getting much response from them at the moment. Whether that means they are aware of issues and are beavering about in the background trying to sort it or they are not giving it much attention I have no idea :(

  • VivekJhaveriVivekJhaveri USMember

    Xamarin.Mac has always seemed really poorly supported. I don't know why they charge full price for a business license.

    Xamarin folks - can you please provide more information about the state of Xamarin.Mac, both in terms of this issue and overall stability? It feels like a stepchild in the Xamarin lineup.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    I did actually get a response from support today, even if it was just to tell us to do something we'd actually already done and already communicated to them :(

  • MikeCodesDotNetMikeCodesDotNet GBXamarin Team Xamurai

    Hi Keith,

    We are actively investigating the issue. We've found the issue is propagating in native code which has added to the difficulty in locating the cause of the issue but I am currently in the room with 3 of our Mac engineers all working on finding a solution for you.

    Once they have located the cause of the problem then they can set about finding a solution for you and we will be in touch.

    All the best,
    Mike

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Yes I see that in an email this morning, my frustration was around getting no response from support for over a week but we seem to be on track now so fingers crossed and thank you.

Sign In or Register to comment.