JDK-8242544 : CMD+ENTER key event crashes the application when invoked on dialog
  • Type: Bug
  • Component: javafx
  • Sub-Component: window-toolkit
  • Affected Version: 8u261,openjfx11,openjfx14
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • CPU: x86
  • Submitted: 2020-04-09
  • Updated: 2022-02-16
  • Resolved: 2022-01-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 Other
8u331Fixed openjfx11.0.15Fixed
Related Reports
Blocks :  
Description
ADDITIONAL SYSTEM INFORMATION :
Tested on HighSierra (10.13.6) and (Catalina 10.15.3) and the application crashes on both.
Java 14
JavaFx 13, JavaFx 14

A DESCRIPTION OF THE PROBLEM :
When adding an event handler that is closing the dialog via CMD+ENTER or CTRL+ENTER key combination, this crashes the entire application on MacOs.

This does NOT happen on Windows or Linux.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Click launch dialog button (the dialog should open)
2. Press ALT+ENTER (the dialog should be closed)
3. Click launch dialog button again (the dialog should open)
4. Press CMD+ENTER
5. The application will crash

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Application should not crash.
ACTUAL -
2020-04-09 20:18:49.116 java[788:13938] CGLChoosePixelFormat: No matching pixel format exists for the requested attributes, trying again with limited capabilities
ALT + ENTER
Apply processed
2020-04-09 20:18:52.754 java[788:13938] CGLChoosePixelFormat: No matching pixel format exists for the requested attributes, trying again with limited capabilities
META + ENTER
Apply processed
2020-04-09 20:18:53.838 java[788:13938] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff563cd66b __exceptionPreprocess + 171
	1   libobjc.A.dylib                     0x00007fff7d6da942 objc_exception_throw + 48
	2   CoreFoundation                      0x00007fff5640d77c _CFThrowFormattedException + 194
	3   CoreFoundation                      0x00007fff562f008f -[__NSArrayM objectAtIndex:] + 175
	4   AppKit                              0x00007fff53b041a8 -[NSView performKeyEquivalent:] + 172
	5   AppKit                              0x00007fff541ab0f7 -[NSWindow _commonPerformKeyEquivalent:conditionally:] + 79
	6   libglass.dylib                      0x0000000126a1ae30 -[GlassWindow_Normal performKeyEquivalent:] + 64
	7   AppKit                              0x00007fff540704fb routeKeyEquivalent + 454
	8   AppKit                              0x00007fff5406dce0 -[NSApplication(NSEvent) sendEvent:] + 1096
	9   libglass.dylib                      0x0000000126a0a435 +[GlassApplication enterNestedEventLoopWithEnv:] + 213
	10  libglass.dylib                      0x0000000126a0aeaa Java_com_sun_glass_ui_mac_MacApplication__1enterNestedEventLoopImpl + 74
	11  ???                                 0x00000001119e16b0 0x0 + 4590540464
)
libc++abi.dylib: terminating with uncaught exception of type NSException
[ERROR] Command execution failed.
org.apache.commons.exec.ExecuteException: Process exited with an error: 134 (Exit value: 134)

---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class CrashMe extends Application {

    @Override
    public void start(Stage stage) {
        ////////////////////////////////////////
        // create main screen
        ////////////////////////////////////////
        Button launchButton = new Button("Launch dialog");
        VBox vbox = new VBox(launchButton);
        Scene scene = new Scene(new StackPane(vbox), 640, 480);
        stage.setScene(scene);

        ////////////////////////////////////////
        // dialog which crashes the application
        ////////////////////////////////////////
        Button clickMe = new Button("Close dialog");
        BorderPane pane = new BorderPane(clickMe);
        Dialog dialog = new Dialog(stage, pane);
        Runnable dialogApply = () -> {
            System.out.println("Apply processed");
            dialog.close();
        };
        dialog.setApply(dialogApply);
        clickMe.setOnAction(e -> dialogApply.run());

        ////////////////////////////////////////
        // wire button on main screen to launch the dialog
        ////////////////////////////////////////
        launchButton.setOnAction(e -> {
            dialog.showAndWait();
        });
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

    public static class Dialog extends Stage {
        private Runnable apply;

        public Dialog(Stage owner, Parent layout) {
            super(StageStyle.DECORATED);
            Scene layoutScene = new Scene(layout, 500, 500);
            this.setScene(layoutScene);

            layoutScene.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
                if (event.getCode() == KeyCode.ENTER && event.isShortcutDown()) {
                    // this crashes the app on MacOs
                    System.out.println("META + ENTER");
                    if (apply != null) {
                        apply.run();
                    }
                    event.consume();
                    return;
                }

                if (event.getCode() == KeyCode.ENTER && event.isAltDown()) {
                    // this does not crash the app on MacOs
                    System.out.println("ALT + ENTER");
                    if (apply != null) {
                        apply.run();
                    }
                    event.consume();
                    return;
                }
            });

            this.hide();
            this.initModality(Modality.APPLICATION_MODAL);
            this.initOwner(owner);
            this.setResizable(true);
        }

        public void setApply(Runnable apply) {
            this.apply = apply;
        }

        @Override
        public void close() {
            super.close();
        }
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
ALT+ENTER does not crash the application
Clicking directly on button does not crash the application

FREQUENCY : always



Comments
A pull request was submitted for review. URL: https://git.openjdk.java.net/jfx11u/pull/72 Date: 2022-02-16 13:40:23 +0000
16-02-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jfx17u/pull/32 Date: 2022-02-11 16:48:35 +0000
11-02-2022

Changeset: a2a0acff Author: Martin Fox <beldenfox@users.noreply.github.com> Committer: Kevin Rushforth <kcr@openjdk.org> Date: 2022-01-12 19:33:03 +0000 URL: https://git.openjdk.java.net/jfx/commit/a2a0acff66727167bfca879bf908361433e74791
12-01-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jfx/pull/714 Date: 2022-01-11 22:18:53 +0000
11-01-2022

Raising this to P2 since there is no known workaround.
11-01-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jfx/pull/704 Date: 2021-12-29 00:44:44 +0000
29-12-2021

I ran into this while investigating JDK-8205915. Luckily this was way easier to investigate. Long story short, while closing the window JavaFX sets the window's view to null. Java_com_sun_glass_ui_mac_MacWindow__1setView turns around and sets the window's contentView to nil (look for the call to performSelectorOnMainThread:withObject:waitUntilDone:). This works inside a keyDown: handler (ALT + ENTER) but not inside processKeyEquivalent: (CMD + ENTER). I can reproduce this crash in a standalone Mac app. One possible fix is to short-circuit the default implementation of NSWindow performKeyEquivalent by changing the implementation in GlassWindow.m from this: BOOL result = [super performKeyEquivalent:theEvent]; to this BOOL result = [self.contentView performKeyEquivalent:theEvent]; Another is to not set the contentView to nil but instead to a dummy NSView. By the way, Apple discourages apps from overriding the NSWindow version of performKeyEquivalent. I doubt short-circuiting it entirely is the right solution.
20-12-2021

I also see this behavior on macOS 11.5 (Big Sur). It consistently crashes regardless of which version of JDK I use.
21-09-2021

I have recently upgraded to BigSur and now I see this crash even with JDK11b19 and JDK8u251. The same was not happening on Catalina.
21-09-2021

It is also now reproducible as of JDK 8u261. This is possibly related to the compiler update (Xcode + MacOSX SDK) that was done in JDK 11+20 and in JDK 8u261.
10-09-2021

I can confirm that this issue is reproducible from jdk11b20, works fine before that. I have used javafx-sdk-11.0.1 to confirm this. I will try to find the exact commit which could have caused this issue
07-09-2021

I can reproduce this. It fails on openjfx11 and later. It works without crashing on JDK 10 and works on recent JDK 8 update releases.
13-04-2020