gluonhq / gluonfx-maven-plugin

Plugin that simplifies creating native images for Java/JavaFX maven projects
BSD 3-Clause "New" or "Revised" License
194 stars 40 forks source link

(macos)Abnormal program termination #206

Open mbbee opened 4 years ago

mbbee commented 4 years ago

This code behaves only wrong, if compiled to native-image in macos (eg. Windows works). The binary file does not reach the marked "// problematic location".

This code aslo works well when started within eclipse ...
-> as i said, only macos native-image is problematic Please help! thx

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;

public class TestJavaFXnativeMacos {
    private static AtomicBoolean startApp = new AtomicBoolean(false);
    private static AtomicBoolean runningSync = new AtomicBoolean(true);

    final static CountDownLatch waitSyncLatch = new CountDownLatch(1);
    final static CountDownLatch askContinueLatch = new CountDownLatch(1);

    private static Alert syncDialog = null;
    private static Thread syncThread = null;

    public static void main(String[] args) {
        Platform.startup(() -> {
        });
        Platform.setImplicitExit(false);

        try {
            start();
        } catch (Throwable e) {
            System.err.println(e.getLocalizedMessage());
        }

        System.out.println("exiting javafx...");
        Platform.exit();
    }

    private static void start() throws InterruptedException {
        System.out.println("starting ....");
        Platform.runLater(() -> {
            syncDialog = new Alert(Alert.AlertType.INFORMATION);
            syncDialog.setTitle("prepare app");
            syncDialog.setHeaderText("Syncing app ...");
            syncDialog.getButtonTypes().clear();
            syncDialog.getButtonTypes().addAll(ButtonType.CANCEL);
            if (syncDialog.showAndWait().get() == ButtonType.CANCEL) {
                System.out.println("button cancel pressed ...");
                runningSync.set(false);
            }
            waitSyncLatch.countDown();
        });
        syncThread = new Thread(() -> {
            int i = 0;
            int end = 5;
            while (runningSync.get() && i < end) {
                System.out.println("fake sync ... " + (i+1) + " of " + end);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i++;
            }
            Platform.runLater(() -> {
                syncDialog.close();
            });
            waitSyncLatch.countDown();
        });
        syncThread.setDaemon(true);
        syncThread.start();

        waitSyncLatch.await();
        System.out.println("sync ended ...");
        System.out.println("asking user to start app - checkpoint 1");
        Platform.runLater(() -> {
            System.out.println("asking user to start app - checkpoint 2");// problematic location
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            System.out.println("asking user to start app - checkpoint 3");
            alert.setTitle("App");
            alert.setHeaderText("Start app ?");
            alert.setOnCloseRequest(event -> {
            });

            if (alert.showAndWait().get() == ButtonType.CANCEL) {
                startApp.set(false);
            } else {
                startApp.set(true);
            }
            askContinueLatch.countDown();
        });
        System.out.println("let main thread wait ....");
        askContinueLatch.await();
        System.out.println("startApp: " + startApp.get());
        System.out.println("App ended ....");
    }
}
mbbee commented 4 years ago

It has something to do with Platform.setImplicitExit(false);