osx_app_in_plain_c icon indicating copy to clipboard operation
osx_app_in_plain_c copied to clipboard

Fixes for menu not being accessible and crash on macbookpro with touchbar

Open soywiz opened this issue 5 years ago • 1 comments

Menu not being accessible is due to creating the menu where some API stuff is not yet ready at the MacOS OS level. Some people suggested to do some dirty hacks to avoid this "bug", but what worked reliably to me is to create the menu and to bring up the window after the applicationDidFinishLaunching event on the application delegate:

Check this (kotlin port using JNA of your code): https://github.com/soywiz/jna-cocoa/blob/e2e55d271644da30a995e5c0a747377e66536d51/src/main/kotlin/HelloJna.kt#L26

It seems that new macbok pros with touchbar have consistent crashes with this code (trying to conform protocol). After struggling a lot, we found that you missed calling the objc_registerClassPair function for each objc_allocateClassPair. I solved it here: https://github.com/soywiz/jna-cocoa/blob/e2e55d271644da30a995e5c0a747377e66536d51/src/main/kotlin/Cocoa.kt#L98

In my case I'm allocating the class pairs, then adding the methods and then calling the objc_registerClassPair to somehow finalize the class definition.

It happens on macbookprops with touchbar only since normal apple computers doesn't do anything reflective with your app/app delegates/window delegates, but when there is touchbar it seems that there is a new protocol, and that the app itself check if your app is implementing that protocol to determine whether to call it or not, and crashing with class_conformsToProtocol because the class is not fully finalized/available to other processes or whatever.

More info about the crash here: https://github.com/korlibs/korge/issues/48

Hope it helps other people!

soywiz avatar Dec 11 '19 10:12 soywiz

I am running into the same issue. Here's the stack trace:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x44)
    frame #0: 0x00007fff6a71ee05 libobjc.A.dylib`class_conformsToProtocol + 313
libobjc.A.dylib`class_conformsToProtocol:
->  0x7fff6a71ee05 <+313>: testl  %eax, 0x44(%rbx)
    0x7fff6a71ee08 <+316>: jne    0x7fff6a71ee1b            ; <+335>
    0x7fff6a71ee0a <+318>: movq   0x8(%rbx), %rdi
    0x7fff6a71ee0e <+322>: callq  0x7fff6a717a28            ; getProtocol(char const*)
Target 2: (cyan_debug) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x44)
  * frame #0: 0x00007fff6a71ee05 libobjc.A.dylib`class_conformsToProtocol + 313
    frame #1: 0x00007fff6a71eca2 libobjc.A.dylib`-[NSObject conformsToProtocol:] + 47
    frame #2: 0x00007fff2f195301 AppKit`-[NSApplication(NSTouchBarFinder) NS_touchBarProviders] + 403
    frame #3: 0x00007fff2f19632d AppKit`_NSTouchBarFinderGatherProvidersForContainer + 64
    frame #4: 0x00007fff2f19645f AppKit`_NSTouchBarFinderGatherProvidersForContainer + 370
    frame #5: 0x00007fff2f19645f AppKit`_NSTouchBarFinderGatherProvidersForContainer + 370
    frame #6: 0x00007fff2f19599d AppKit`___NSTouchBarFinderSetNeedsUpdateOnMain_block_invoke + 240
    frame #7: 0x00007fff2f196268 AppKit`___NSRunLoopObserverCreateWithHandler_block_invoke + 41
    frame #8: 0x00007fff3185e335 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    frame #9: 0x00007fff3185e267 CoreFoundation`__CFRunLoopDoObservers + 457
    frame #10: 0x00007fff3185ce79 CoreFoundation`CFRunLoopRunSpecific + 521
    frame #11: 0x00007fff30489abd HIToolbox`RunCurrentEventLoopInMode + 292
    frame #12: 0x00007fff304896f4 HIToolbox`ReceiveNextEventCommon + 359
    frame #13: 0x00007fff30489579 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 64
    frame #14: 0x00007fff2eacf039 AppKit`_DPSNextEvent + 883
    frame #15: 0x00007fff2eacd880 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1352

It seems like deferring the menu creation until applicationDidFinishLaunching may be a bit of a hack. @soywiz - did adding all the missing objc_registerClassPairs (for each objc_allocateClassPair) fix the issue? Or was the only way to fix this to defer menu creation until after the application finished launching? Would be great to figure out exactly how to fix for the C source

nickav avatar Nov 04 '20 16:11 nickav