On Fri, 16 May 2025 14:38:20 GMT, Michael Strauß <[email protected]> wrote:
> When an exception is thrown from `AnimationTimer::handle`, the JavaFX
> application freezes. The reason is that the user exception will bubble up
> into framework code, preventing the normal operation of JavaFX.
>
> The following program demonstrates the defect:
>
>
> public class FailingAnimationTimer extends Application {
> @Override
> public void start(Stage stage) throws Exception {
> var button = new Button("start timer");
> button.setOnAction(_ -> {
> var timer = new AnimationTimer() {
> @Override
> public void handle(long l) {
> throw new RuntimeException("foo");
> }
> };
>
> timer.start();
> });
>
> var root = new HBox();
> root.getChildren().add(new TextField("test"));
> root.getChildren().add(button);
> stage.setScene(new Scene(root));
> stage.show();
> }
> }
>
>
> The solution is to not allow user exceptions to bubble up into animation
> framework code. If an exception occurs, it is instead sent to the current
> thread's uncaught exception handler. This is the same thing that we already
> do for exceptions thrown by invalidation listeners and change listeners.
>
> In addition to that, a failing animation timer has the potential to spam
> logs, which is why I introduced a cut-off value at 100 exceptions for each
> individual timer, after which no further exceptions from this particular
> timer are sent to the uncaught exception handler. After reaching the cut-off
> value, the following warning is logged:
>
> `WARNING: Too many exceptions thrown by AnimationTimer, ignoring further
> exceptions. The cut-off number can be set with the system property
> com.sun.scenario.animation.failingTimerThreshold (current = 100).`
modules/javafx.graphics/src/main/java/com/sun/scenario/animation/AbstractPrimaryTimer.java
line 66:
> 64: private final int PULSE_DURATION_TICKS =
> getPulseDuration((int)TickCalculation.fromMillis(1000));
> 65:
> 66: private static final String FAILING_TIMER_THRESHOLD_PROP =
> "com.sun.scenario.animation.failingTimerThreshold";
maybe a comment describing what this property does would be helpful for the
digital paleontologist of the future
modules/javafx.graphics/src/main/java/com/sun/scenario/animation/AbstractPrimaryTimer.java
line 331:
> 329: }
> 330:
> 331: receiversLocked = false;
if L327 throws an exception, `receiversLocked` will not get cleared.
modules/javafx.graphics/src/main/java/com/sun/scenario/animation/AbstractPrimaryTimer.java
line 347:
> 345: }
> 346:
> 347: animationTimersLocked = false;
same here
-------------
PR Review Comment: https://git.openjdk.org/jfx/pull/1811#discussion_r2093467739
PR Review Comment: https://git.openjdk.org/jfx/pull/1811#discussion_r2093466067
PR Review Comment: https://git.openjdk.org/jfx/pull/1811#discussion_r2093466315