Open SyntevoAlex opened 2 years ago
Here's my native snippet I used for testing (compile with clang++ -std=c++11 -Wno-deprecated-declarations --debug -framework Cocoa -framework Carbon SWT_578171_macOS_crash_ShowWindowWhenBrowsingMenu.mm -o SWT_578171_macOS_crash_ShowWindowWhenBrowsingMenu
)
SWT_578171_macOS_crash_ShowWindowWhenBrowsingMenu.mm.txt
SWT snippet is already in the repo, see Bug578171_macOS_JvmCrash_ShowMenuWindow
I will not be able to handle this soon, so everyone is welcome to fix that.
Can we simply remove cancelRootMenuTracking
and preventShellActivateJvmCrash
to test?
Or replace with menubar.cancelTracking()
?
Removing preventShellActivateJvmCrash()
will restore the crash that is currently suppressed in #277.
Removing cancelRootMenuTracking()
will remove the cause of the crash. I have no idea if it's still needed at all.
If it's needed, then replacing with menubar.cancelTracking()
is the most reasonable fix, but I haven't investigated why it was changed to CancelMenuTracking()
years ago and if it's still important.
Comment in that part of the code:
* For some reason, NSMenu.cancelTracking() does not dismisses
* the menu right away when the menu bar is set in a stacked
* event loop. The fix is to use CancelMenuTracking() instead.
Yes, I seen this comment, of course. It doesn't quite explain what does it really fix, and why cancelling tracking is needed in the first place.
Can you make a PR with these changes (and use menubar.cancelTracking()
) for testing?
(I put the javadoc comment here for other people to see)
Here, I removed both: #338 With very quick testing, it doesn't seem that any form of cancelling tracking is needed.
It was added in 080eb4cfdf4de7f642c2aaa74935d2369b548d27
I removed CancelMenuTracking
and tried to recreate the steps in https://bugs.eclipse.org/bugs/show_bug.cgi?id=270379 ~but could not because I couldn't do "Then click the Help menu again"~
Edit: see below
I removed CancelMenuTracking and tried to recreate the steps in https://bugs.eclipse.org/bugs/show_bug.cgi?id=270379 but could not because I couldn't do "Then click the Help menu again"
Actually I am wrong. I did manage to follow those steps and see the problem.
And I tried the same thing using menubar.cancelTracking()
and I saw the same problem.
The steps in 270379 can be tricky to follow. So in our RCP app we have a Help menu to which I added an Action
with this run method:
public void run() {
Display.getDefault().timerExec(2000, () -> {
MessageDialog.openInformation(null, "Test", "Test");
});
}
CancelMenuTracking
is not calledIn fact, while testing above with not using CancelMenuTracking
I got lots of NPEs:
java.lang.NullPointerException
at org.eclipse.ui.internal.handlers.LegacyHandlerService.registerLegacyHandler(LegacyHandlerService.java:164)
at org.eclipse.ui.internal.handlers.LegacyHandlerService.registerLegacyHandler(LegacyHandlerService.java:158)
at org.eclipse.ui.internal.handlers.LegacyHandlerService.activateHandler(LegacyHandlerService.java:306)
at org.eclipse.ui.internal.handlers.LegacyHandlerService.activateHandler(LegacyHandlerService.java:299)
at org.eclipse.ui.SubActionBars.setGlobalActionHandler(SubActionBars.java:549)
at org.eclipse.gef.ui.actions.ActionBarContributor.setActiveEditor(ActionBarContributor.java:161)
at org.eclipse.ui.internal.EditorActionBars.partChanged(EditorActionBars.java:335)
at org.eclipse.ui.internal.WorkbenchPage.updateActivations(WorkbenchPage.java:323)
at org.eclipse.ui.internal.WorkbenchPage$E4PartListener.partActivated(WorkbenchPage.java:212)
at org.eclipse.e4.ui.internal.workbench.PartServiceImpl$2.run(PartServiceImpl.java:250)
Note that my tests were done with preventShellActivateJvmCrash
removed. If that is present then CancelMenuTracking
is not needed in Display#setMenuBar
in the above test. Of course it may be needed in other cases.
My conclusion is not to remove CancelMenuTracking
unless an alternative can be found to stop above situation.
CancelMenuTracking() is not supposed to be called from 64-bit code SWT uses API it shouldn't be using
Maybe, but it does still prevent the above situation, so it is doing something.
Thanks for testing! Now we "just" need to find a better solution for an initial problem without making things even uglier :)
To make testing even easier I created a simple snippet. Instructions are in the snippet and on the app's label when run.
This is to test the effect of removing or commenting out this line in Display#cancelRootMenuTracking
(line 4930 in current version):
OS.CancelMenuTracking (rootMenu, true, 0);
~I think I've found a clue.~
~If we want to use NSMenu#cancelTracking
instead of OS.CancelMenuTracking
the problem lies in when we call it.~
As POC, replace Display#cancelRootMenuTracking()
with this:
static void cancelRootMenuTracking () {
NSMenu menubar = getCurrent().application.mainMenu();
menubar.cancelTracking();
}
~This pretty much solve my test case, above,~ and also the crash in Bug578171_macOS_JvmCrash_ShowMenuWindow
Edit - nope. Menu items are left hanging in the air in my test snippet. I should have tested this more before commenting here. Ignore above.
In Bug 578171, a crash was discovered. Back then I didn't realize that it's triggered by
CancelMenuTracking()
, and thought that it was triggered by showing aShell
when browsing menu bar.Today I spent time to make a native snippet to report bug to Apple, but when doing so, I found that
CancelMenuTracking()
menubar.cancelTracking()
doesn't trigger itI also found that
CancelMenuTracking()
is not supposed to be called from 64-bit code, seeXcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Menus.h
:Here, note
[32-bit only]
and#if !__LP64__
.In order to circumvent that, SWT uses dynamic linking to access the API:
To summarize:
The suggested fix is to
CancelMenuTracking()