Sometimes the Binding is not working

Hi,
I have an app written in xamarin.mac.
Sometimes i see that the connection between the gui and the code is not responsive.
I mean I have a simple screen with 2 buttons in a viewcontroller, and sometimes the push on the button does not arrive in the targeted action.
I done the binding as "Action Invocation" with "Selector name".
it is hard to reproduce but sometimes it happens.

Has anyone saw this behavior?
Thank you
Evgeny.

Answers

  • evgeny_shteinevgeny_shtein Member ✭✭

    Hi,
    After further investigation i was able to pin point the issue.
    when the viewcontroller is shown and it stays in front for some time the Destructor is called and i get the "unrecognized selector sent to instance" error, and sometimes even the app crushes.

    Why is the Destructor called when the view is on front?

    Evgeny

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Maybe you are not holding onto a Window controller and it is being garbage collected. When you disposed a window controller it closes the window.

    Also, when you have intermittent issues, throw a GC.Collect (2) or two will often flush them out (forces a full collection).

  • evgeny_shteinevgeny_shtein Member ✭✭

    The window controller is being created by the interface builder, as I'm using a storyboard entry point and not creating the window programatically.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Without code for anyone on the forums to look at, the best you are able to get is guesses. Looks like you have some debugging ahead.

    I would start figuring out the following:

    • Who is closing your window controller. Add some lifecycle methods and print/debug into them to see if you can figure out who's the culprit.

    • Try to make your inconsistent crash consistent. If it is GC related, this logic shoved somewhere in startup can often help "shake out" failures

      new System.Threading.Thread (() =>
      {
      while (true) {
      System.Threading.Thread.Sleep (500);
      GC.Collect ();
      }
      }).Start ();

  • evgeny_shteinevgeny_shtein Member ✭✭

    I see the problem.

    All of my view controllers are being created by the interface builder.

    From the moment where my view controller is being created, he is eligible for garbage collection.

    Doesn't the framework keep references of the view controllers I'm creating?

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai
    edited March 2018

    I'm not sure I'm following (hard to do without an example). If the ObjC runtime is keeping a reference to your view controller, then it will not be disposed of (or should not be).

    However, if you reference that item in C#, say by instancing up a window controller (from your storyboard) and asking it to show, then you need to keep it around as long as you want the window.

  • evgeny_shteinevgeny_shtein Member ✭✭
    edited March 2018

    Hi,
    I tried to replicate the same issue with MacControls sample.
    after doing the following changes:

    --- a/MacControls/MacControls/ButtonsViewController.cs
    +++ b/MacControls/MacControls/ButtonsViewController.cs
    @@ -12,6 +12,11 @@ namespace MacControls
                    #region Constructors
                    public ButtonsViewController (IntPtr handle) : base (handle)
                    {
    +                       Console.WriteLine("ButtonsViewController CTOR");
    +               }
    +               ~ButtonsViewController()
    +               {
    +                       Console.WriteLine("~ButtonsViewController");
                    }
                    #endregion
    
    @@ -21,23 +26,32 @@ namespace MacControls
                            base.ViewWillAppear ();
    
                            // Wireup events
    -                       ButtonOutlet.Activated += (sender, e) = {
    -                               FeedbackLabel.StringValue = "Button Outlet Pressed";
    -                       };
    +                       //ButtonOutlet.Activated += (sender, e) = {
    +                       //      FeedbackLabel.StringValue = "Button Outlet Pressed";
    +                       //};
    
    -                       DisclosureButton.Activated += (sender, e) = {
    -                               LorumIpsum.Hidden = (DisclosureButton.State == NSCellStateValue.On);
    -                       };
    +                       //DisclosureButton.Activated += (sender, e) = {
    +                       //      LorumIpsum.Hidden = (DisclosureButton.State == NSCellStateValue.On);
    +                       //};
    
    -                       RoundedGradient.Activated += (sender, e) = {
    -                               FeedbackLabel.StringValue = "Rounded Gradient Pressed";
    -                       };
    +                       //RoundedGradient.Activated += (sender, e) = {
    +                       //      FeedbackLabel.StringValue = "Rounded Gradient Pressed";
    +                       //};
                    }
                    #endregion
    
                    #region Button Action Handlers
                    partial void ButtonAction (Foundation.NSObject sender) {
    -                       FeedbackLabel.StringValue = "Button Action Pressed";
    +                       FeedbackLabel.StringValue = "GC is called in 500 mSec";
    +
    +                       new System.Threading.Thread(() =
    +            {
    +                while (true)
    +                {
    +                    System.Threading.Thread.Sleep(500);
    +                    GC.Collect();
    +                }
    +            }).Start();
                    }
    

    and going to ButtonViewController and pressing ButtonAction button I see that the destructor is being called.

    What is the best way to save a strong reference to the new view controller?

    As I can understand from this example, the registration to the button's "Activated" event is what keeps the view controller from being GC.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Consider using the "code" formatting when you post diffs, it doesn't destroy the formatting (I fixed your last post).

    So your snipped does not show how your window controllers are being spun up. Does your app just load the default storyboard and "go" with no additional startup? Are you calling NSStoryboard. or NSNib APIs?

    Once again, without a sample showing your issue, it is very difficult to get a handle on your issue, since we only see small snipped of your application.

    I currently don't have any evidence that NSWindowControllers aren't doing lifetimes correctly. I just tested a quick "make the default window/windowcontroller in a new Xamarin.Mac application C# based and GC.Collect and it seemed to work fine.

  • tomer_domshlaktomer_domshlak ILMember ✭✭
    Hi Chris,

    I'm Evgeny's team mate.

    Thank you for your quick response.

    The problem is not with NSWindowController, but rather with NSViewController.

    We are not instantiating neither the window nor the views programatically.
    The instantiation is done by the interface builder, which seems to me like the main cause of the problem (though I haven't tried any other technique to support that claim).

    Important to say that we've managed to come around it, so we are OK now.

    Tomorrow we'll work together on some sample code that will easily reproduce the issue.
  • evgeny_shteinevgeny_shtein Member ✭✭

    Hi Chris,
    in order to reproduce the issue i changed the MacContorols sample app with the diff i already added.

    https://github.com/xamarin/mac-samples/tree/master/MacControls

    I am also uploading the modified project to be more convenient.

    steps to reproduce the issue:

    Open the app.
    Go to Buttons view,
    Press on the Button Action button,
    You will see that it will write that the GC will be executed in 500 mSec.

    After that if you press the button again the app will crash because the ViewController's Destructor has been called.

    Thank you.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    I tried your sample and I was unable to crash it as described.

    ButtonsViewController CTOR
    Thread started:  #2
    ~ButtonsViewController
    ButtonsViewController CTOR
    ~ButtonsViewController
    ButtonsViewController CTOR
    Thread started:  #3
    ~ButtonsViewController
    
  • evgeny_shteinevgeny_shtein Member ✭✭

    @ChrisHamons said:
    I tried your sample and I was unable to crash it as described.

    ButtonsViewController CTOR
    Thread started:  #2
    ~ButtonsViewController
    ButtonsViewController CTOR
    ~ButtonsViewController
    ButtonsViewController CTOR
    Thread started:  #3
    ~ButtonsViewController
    

    Please stay on the same view and press the button several times without going to different view controllers

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    I did. I hit it about a dozen times and left it for over a minute.

    What version of Xamarin.Mac are you using?

  • evgeny_shteinevgeny_shtein Member ✭✭

    Visual Studio Community 2017 for Mac
    Version 7.4.1 (build 48)

    this is what i got after pressing 2 times on the button:
    018-04-04 08:51:28.096 MacControls[61512:10066821] Unknown Window class (null) in Interface Builder file,
    creating generic Window instead
    2018-04-04 08:51:28.340 MacControls[61512:10066821] WARNING: The SplitView is not layer-backed, but trying to use overlay sidebars.. implicitly layer-backing for now. Please file a radar against this app if you see this.
    ButtonsViewController CTOR
    Thread started: #2
    Button is pressed
    ~ButtonsViewController
    Stacktrace:

    at <0xffffffff>
    at (wrapper managed-to-native) AppKit.NSApplication.NSApplicationMain (int,string[]) [0x0005a] in <7d22d19c98ed41dd98ad4ca0e3900efe>:0
    at AppKit.NSApplication.Main (string[]) [0x00041] in /Library/Frameworks/Xamarin.Mac.framework/Versions/4.2.1.28/src/Xamarin.Mac/AppKit/NSApplication.cs:100
    at MacControls.MainClass.Main (string[]) [0x00007] in /Users/dev/workspace/mac-samples/MacControls/MacControls/Main.cs:10
    at (wrapper runtime-invoke) .runtime_invoke_void_object (object,intptr,intptr,intptr) [0x00051] in <27f49891d0674631b3d010b483b1c100>:0

    Native stacktrace:

    0   MacControls                         0x000000010a8333b1 mono_handle_native_crash + 257
    1   MacControls                         0x000000010a7ae116 altstack_handle_and_restore + 70
    2   libobjc.A.dylib                     0x00007fffcbfc705d objc_msgSend + 29
    3   AppKit                              0x00007fffb53a9721 -[NSApplication(NSResponder) sendAction:to:from:] + 456
    4   AppKit                              0x00007fffb4e8dcc4 -[NSControl sendAction:to:] + 86
    5   AppKit                              0x00007fffb4e8dbec __26-[NSCell _sendActionFrom:]_block_invoke + 136
    6   libsystem_trace.dylib               0x00007fffccaed3a7 _os_activity_initiate_impl + 53
    7   AppKit                              0x00007fffb4e8db44 -[NSCell _sendActionFrom:] + 128
    8   AppKit                              0x00007fffb4ed0539 -[NSButtonCell _sendActionFrom:] + 98
    9   libsystem_trace.dylib               0x00007fffccaed3a7 _os_activity_initiate_impl + 53
    10  AppKit                              0x00007fffb4e8c426 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2481
    11  AppKit                              0x00007fffb4ed0272 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 798
    12  AppKit                              0x00007fffb4e8addb -[NSControl mouseDown:] + 832
    13  AppKit                              0x00007fffb552524f -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 6341
    14  AppKit                              0x00007fffb5521a6c -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 1942
    15  AppKit                              0x00007fffb5520f0a -[NSWindow(NSEventRouting) sendEvent:] + 541
    16  AppKit                              0x00007fffb53a5681 -[NSApplication(NSEvent) sendEvent:] + 1145
    17  AppKit                              0x00007fffb4c20427 -[NSApplication run] + 1002
    18  AppKit                              0x00007fffb4beae0e NSApplicationMain + 1237
    19  ???                                 0x000000010e9e49f0 0x0 + 4540221936
    20  ???                                 0x000000010e9e45a3 0x0 + 4540220835
    21  MacControls                         0x000000010a845cea mono_jit_runtime_invoke + 1338
    22  MacControls                         0x000000010a9128b4 do_runtime_invoke + 84
    23  MacControls                         0x000000010a915ee9 do_exec_main_checked + 137
    24  MacControls                         0x000000010a7a529f mono_jit_exec + 287
    25  MacControls                         0x000000010a7a7b5d mono_main + 9325
    26  MacControls                         0x000000010a7494ae xamarin_main + 1182
    27  MacControls                         0x000000010a74a404 main + 36
    28  libdyld.dylib                       0x00007fffcc8bb235 start + 1
    

    Debug info from gdb:

    (lldb) command source -s 0 '/tmp/mono-gdb-commands.0xrBJU'
    Executing commands in '/tmp/mono-gdb-commands.0xrBJU'.
    (lldb) process attach --pid 61512
    Process 61512 stopped

    • thread #1, name = 'tid_307', queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
      frame #0: 0x00007fffcc9ea3ee libsystem_kernel.dylib__wait4 + 10 libsystem_kernel.dylib__wait4:
      -> 0x7fffcc9ea3ee <+10>: jae 0x7fffcc9ea3f8 ; <+20>
      0x7fffcc9ea3f0 <+12>: movq %rax, %rdi
      0x7fffcc9ea3f3 <+15>: jmp 0x7fffcc9e2cd4 ; cerror
      0x7fffcc9ea3f8 <+20>: retq
      Target 0: (MacControls) stopped.

    Executable module set to "/Users/dev/workspace/mac-samples/MacControls/MacControls/bin/Debug/MacControls.app/Contents/MacOS/MacControls".
    Architecture set to: x86_64h-apple-macosx.
    (lldb) thread list
    Process 61512 stopped

    • thread #1: tid = 0x999b85, 0x00007fffcc9ea3ee libsystem_kernel.dylib__wait4 + 10, name = 'tid_307', queue = 'com.apple.main-thread', stop reason = signal SIGSTOP thread #2: tid = 0x999b8f, 0x00007fffcc9ea44e libsystem_kernel.dylib__workq_kernreturn + 10
      thread #3: tid = 0x999b90, 0x00007fffcc9ea44e libsystem_kernel.dylib__workq_kernreturn + 10 thread #4: tid = 0x999b98, 0x00007fffcc9e9bf2 libsystem_kernel.dylib__psynch_cvwait + 10, name = 'SGen worker'
      thread #5: tid = 0x999b9a, 0x00007fffcc9e2386 libsystem_kernel.dylibsemaphore_wait_trap + 10, name = 'Finalizer' thread #6: tid = 0x999b9b, 0x00007fffcc9e9df6 libsystem_kernel.dylib__recvfrom + 10, name = 'Debugger agent'
      thread #7: tid = 0x999bd1, 0x00007fffcc9e234a libsystem_kernel.dylibmach_msg_trap + 10, name = 'com.apple.NSEventThread' thread #8: tid = 0x999c80, 0x00007fffcc9e9bf2 libsystem_kernel.dylib__psynch_cvwait + 10, name = 'tid_120b'
      (lldb) thread backtrace all

    • thread #1, name = 'tid_307', queue = 'com.apple.main-thread', stop reason = signal SIGSTOP

      • frame #0: 0x00007fffcc9ea3ee libsystem_kernel.dylib__wait4 + 10 frame #1: 0x000000010a83343e MacControlsmono_handle_native_crash(signal="SIGSEGV", ctx=, info=) at mini-exceptions.c:2726 [opt]
        frame #2: 0x000000010a7ae116 MacControlsaltstack_handle_and_restore(ctx=0x00007fff554eb9f0, obj=0x0000000000000000, stack_ovf=0) at exceptions-amd64.c:856 [opt] frame #3: 0x00007fffcbfc705d libobjc.A.dylibobjc_msgSend + 29
        thread #2
        frame #0: 0x00007fffcc9ea44e libsystem_kernel.dylib__workq_kernreturn + 10 frame #1: 0x00007fffccad448e libsystem_pthread.dylib_pthread_wqthread + 1023
        frame #2: 0x00007fffccad407d libsystem_pthread.dylibstart_wqthread + 13 thread #3 frame #0: 0x00007fffcc9ea44e libsystem_kernel.dylib__workq_kernreturn + 10
        frame #1: 0x00007fffccad4621 libsystem_pthread.dylib_pthread_wqthread + 1426 frame #2: 0x00007fffccad407d libsystem_pthread.dylibstart_wqthread + 13
        thread #4, name = 'SGen worker'
        frame #0: 0x00007fffcc9e9bf2 libsystem_kernel.dylib__psynch_cvwait + 10 frame #1: 0x00007fffccad57fa libsystem_pthread.dylib_pthread_cond_wait + 712
        frame #2: 0x000000010a9cfb9e MacControlsthread_func [inlined] mono_os_cond_wait(mutex=<unavailable>) at mono-os-mutex.h:173 [opt] frame #3: 0x000000010a9cfb8b MacControlsthread_func at sgen-thread-pool.c:165 [opt]
        frame #4: 0x000000010a9cfa35 MacControlsthread_func(data=0x0000000000000000) at sgen-thread-pool.c:196 [opt] frame #5: 0x00007fffccad493b libsystem_pthread.dylib_pthread_body + 180
        frame #6: 0x00007fffccad4887 libsystem_pthread.dylib_pthread_start + 286 frame #7: 0x00007fffccad408d libsystem_pthread.dylibthread_start + 13
        thread #5, name = 'Finalizer'
        frame #0: 0x00007fffcc9e2386 libsystem_kernel.dylibsemaphore_wait_trap + 10 frame #1: 0x000000010a8ac9cc MacControlsfinalizer_thread [inlined] mono_os_sem_wait(flags=MONO_SEM_FLAGS_ALERTABLE) at mono-os-semaphore.h:90 [opt]
        frame #2: 0x000000010a8ac9c1 MacControlsfinalizer_thread at mono-coop-semaphore.h:43 [opt] frame #3: 0x000000010a8ac9b5 MacControlsfinalizer_thread(unused=) at gc.c:866 [opt]
        frame #4: 0x000000010a960550 MacControlsstart_wrapper [inlined] start_wrapper_internal at threads.c:1003 [opt] frame #5: 0x000000010a9604b3 MacControlsstart_wrapper(data=) at threads.c:1063 [opt]
        frame #6: 0x00007fffccad493b libsystem_pthread.dylib_pthread_body + 180 frame #7: 0x00007fffccad4887 libsystem_pthread.dylib_pthread_start + 286
        frame #8: 0x00007fffccad408d libsystem_pthread.dylibthread_start + 13 thread #6, name = 'Debugger agent' frame #0: 0x00007fffcc9e9df6 libsystem_kernel.dylib__recvfrom + 10
        frame #1: 0x000000010a799dbe MacControlssocket_transport_recv(buf="�#", len=11) at debugger-agent.c:1150 [opt] frame #2: 0x000000010a7843d6 MacControlsdebugger_thread [inlined] transport_recv(len=11) at debugger-agent.c:1556 [opt]
        frame #3: 0x000000010a7843b2 MacControlsdebugger_thread(arg=<unavailable>) at debugger-agent.c:10426 [opt] frame #4: 0x000000010a960550 MacControlsstart_wrapper [inlined] start_wrapper_internal at threads.c:1003 [opt]
        frame #5: 0x000000010a9604b3 MacControlsstart_wrapper(data=<unavailable>) at threads.c:1063 [opt] frame #6: 0x00007fffccad493b libsystem_pthread.dylib_pthread_body + 180
        frame #7: 0x00007fffccad4887 libsystem_pthread.dylib_pthread_start + 286 frame #8: 0x00007fffccad408d libsystem_pthread.dylibthread_start + 13
        thread #7, name = 'com.apple.NSEventThread'
        frame #0: 0x00007fffcc9e234a libsystem_kernel.dylibmach_msg_trap + 10 frame #1: 0x00007fffcc9e1797 libsystem_kernel.dylibmach_msg + 55
        frame #2: 0x00007fffb7135434 CoreFoundation__CFRunLoopServiceMachPort + 212 frame #3: 0x00007fffb71348c1 CoreFoundation__CFRunLoopRun + 1361
        frame #4: 0x00007fffb7134114 CoreFoundationCFRunLoopRunSpecific + 420 frame #5: 0x00007fffb4d78f02 AppKit_NSEventThread + 205
        frame #6: 0x00007fffccad493b libsystem_pthread.dylib_pthread_body + 180 frame #7: 0x00007fffccad4887 libsystem_pthread.dylib_pthread_start + 286
        frame #8: 0x00007fffccad408d libsystem_pthread.dylibthread_start + 13 thread #8, name = 'tid_120b' frame #0: 0x00007fffcc9e9bf2 libsystem_kernel.dylib__psynch_cvwait + 10
        frame #1: 0x00007fffccad5833 libsystem_pthread.dylib_pthread_cond_wait + 769 frame #2: 0x000000010a9e1244 MacControlsmono_os_cond_timedwait(cond=0x000000010abf5780, mutex=0x000000010abf5740, timeout_ms=500) at mono-os-mutex.c:44 [opt]
        frame #3: 0x000000010a9e8538 MacControlsmono_thread_info_sleep at mono-coop-mutex.h:102 [opt] frame #4: 0x000000010a9e8512 MacControlsmono_thread_info_sleep [inlined] sleep_interruptable(ms=, alerted=) at mono-threads.c:1270 [opt]
        frame #5: 0x000000010a9e83a0 MacControlsmono_thread_info_sleep(ms=<unavailable>, alerted=<unavailable>) at mono-threads.c:1302 [opt] frame #6: 0x000000010a95a63b MacControlsves_icall_System_Threading_Thread_Sleep_internal(ms=500) at threads.c:1480 [opt]
        frame #7: 0x0000000110bc689b
        frame #8: 0x0000000110bc5463
        frame #9: 0x000000010a845cea MacControlsmono_jit_runtime_invoke(method=<unavailable>, obj=<unavailable>, params=0x000070000864cea8, exc=0x00000000000001f4, error=<unavailable>) at mini-runtime.c:2800 [opt] frame #10: 0x000000010a9128b4 MacControlsdo_runtime_invoke(method=0x00007f91472bc070, obj=0x000000010b48b228, params=0x000070000864cea8, exc=0x0000000000000000, error=0x000070000864ce40) at object.c:2849 [opt]
        frame #11: 0x000000010a96057b MacControlsstart_wrapper at threads.c:1011 [opt] frame #12: 0x000000010a9604b3 MacControlsstart_wrapper(data=) at threads.c:1063 [opt]
        frame #13: 0x00007fffccad493b libsystem_pthread.dylib_pthread_body + 180 frame #14: 0x00007fffccad4887 libsystem_pthread.dylib_pthread_start + 286
        frame #15: 0x00007fffccad408d libsystem_pthread.dylib`thread_start + 13
        (lldb) detach

    =================================================================
    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.

    Process 61512 detached
    (lldb) quit

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    So "7.4.1.48" VSfM doesn't exactly tell me what version of Xamarin.Mac you are using, but assuming you are using the version released at the same time it'd be "4.2.1.28".

    What version of macOS are you using? I'm definitely not seeing that crash locally, so let's try to figure out what the difference is.

  • evgeny_shteinevgeny_shtein Member ✭✭

    Hi,
    I update my os to HighSierra and updated xcode to the latest one also,
    the app stopped crashing but i still can reproduce the issue.

    please change the code of the Button action method to :

    partial void ButtonAction (Foundation.NSObject sender) {
    
        FeedbackLabel.StringValue = $"GC is called in 500 mSec, {DateTime.UtcNow}";
            Console.WriteLine($"Button is pressed,{DateTime.UtcNow}");
            new System.Threading.Thread(() =
                {
                    while (true)
                    {
                        System.Threading.Thread.Sleep(500);
                        GC.Collect();
                    }
                 }).Start();
    }
    

    After pressing the button once you will see that the prints will not be shown on the console and on the app itself ( you can see it by the seconds of the the DateTime.
    that will show you that even that the app is not crushing it will not invoke the method

    Thank you
    Evgeny

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    I am able to reproduce your issue. I'm looking into if it is a sample bug or an API bug now.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    After research, I believe this is a sample bug, and I've filed it here: https://github.com/xamarin/mac-samples/issues/84

Sign In or Register to comment.