Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8124412

Platform.runLater() prevents Application.stop() from being called if given a Runnable that throws and Exception.

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 7u15
    • javafx

      Edit: Sorry, I can't seem to get the formatting right for the code blocks.

      The following application will exit fine if you start it and close the window immediately. However, if you click the 'Click Me' button first, the Application.stop() method will never be called.

      {code}
      public class TestExitApplication extends Application {
          @Override
          public void start(Stage primaryStage) throws Exception {
              try {
                  Scene scene = new Scene(createButton());
                  primaryStage.setScene(scene);
                  primaryStage.setTitle("Echo Client");
                  primaryStage.show();
              } catch (Exception e) {
                  System.out.println("Exiting due to startup failure.");
                  System.exit(1);
              }
          }

          @Override
          public void stop() throws Exception {
              System.out.println("Exiting via call to stop().");
              System.exit(0);
          }

          private Button createButton() {
              Button button = new Button("Click Me!");
              button.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
                  public void handle(ActionEvent actionEvent) {
                      Platform.runLater(new Runnable() {
                          @Override
                          public void run() {
                              throw new RuntimeException("Oh no!");
                          }
                      });
                  }
              });
              return button;
          }

          public static void main(String[] args) {
              System.out.println(VersionInfo.getRuntimeVersion());
              Application.launch(TestExitApplication.class);
          }
      }
      {code}

      The {{PlatformImpl}} class has this block of code:

      {code}
      Toolkit.getToolkit().defer(new Runnable() {
          @Override public void run() {
              try {
                  r.run();
                  pendingRunnables.decrementAndGet();
                  checkIdle();
              } catch (Throwable t) {
                  System.err.println("Exception in runnable");
                  t.printStackTrace();
              }
          }
      });
      {code}

      Shouldn't the decrement of pendingRunnables happen in a finally block? Once a Runnable has failed with an exception, it's not longer pending, right?

      Also, is Platform.runLater() supposed to be swallowing exceptions like that?

            kcr Kevin Rushforth
            rjjfx Ryan J (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: