<AWT Dev> RFR: 8196100: javax/swing/text/JTextComponent/5074573/bug5074573.java fails

Alexander Zuev kizune at openjdk.java.net
Wed Nov 25 17:52:03 UTC 2020

On Wed, 25 Nov 2020 00:15:11 GMT, Sergey Bylokhov <serb at openjdk.org> wrote:

> Here is a fix for one of the annoying bug, which causes random test failures in the CI.
> We have a method Robot.waitForIdle(), which supposed to wait until the java and the native queue stabilized. The common use case is to click on the button or show the window, and call waitForIdle() which will wait until the native event will be dispatched by the X11/Windows/macOS as well as followed Java event(paint/focus/etc event) will be dispatched to the EDT.
> Currently, it is implemented in this way:
>   1. Flush the EventQueue, so all old events will be posted to EDT.
>   2. Flush the native event queue, by posting the native event.
>   3. Flush the EDT, by posting a java event.
>   4. If some events(unrelated to waitForIdle machinery) were dispatched on steps 2. or 3. then repeat since step 1.
> It is implemented that they because the native events caused by the OS usually generate the java events, and the java events may generate native events. So we have to wait for both queues (java/native).
> But it has the next disadvantages:
>  - It is implemented as a busy loop, which does not give a chance for the application to proceed further since it blocks 3 threads EDT/native toolkit thread like appkit/main thread.
> - It throws the InfiniteLoop exception if the number of attempts is bigger than 20. And this limitation is too small because some tests generate much more events during startup.
>  - Note that the timeout value for the realSync method is 10 seconds, and it was assumed that this method will not be executed longer, but it uses this timeout for all events flushing which can lead up to 600 seconds (20 iters * 3  calls * 10 seconds).
> The fix:
>  - Add a small delay to the method, so the app can do something useful when waitForIdle() is called
>  - The timeout=10 second is taken care of, we calculate the "end" time and exits if it is exceeded
>  - The maximum number of attempts is increased to 100 and InfiniteLoop is removed.
> Note that I have made one additional change to the new realSync implementation. At the beginning of the method I call:
>  EventQueue.invokeAndWait(() -> {/*dummy implementation*/});
> It is needed to be sure that we flush the first event on EDT even if we spend more time than 10 seconds.

src/java.desktop/share/classes/sun/awt/SunToolkit.java line 1383:

> 1381:                 it.next().modalityPopped(ev);
> 1382:             }
> 1383:         }

I think that the rationale behind this exception as that in case of really stuck loop we could identify it. Why are we throwing it away? Now when we exceed the maximum allowed number of iterations we are assuming that the native event queue synchronization happened while it might not be the case.

test/jdk/java/awt/Robot/InfiniteLoopException.java line 63:

> 61:         long time = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
> 62:         if (time > 20) {
> 63:             throw new RuntimeException("To slow:" + time);

Typo? Shouldn't it be "Too slow"?


PR: https://git.openjdk.java.net/jdk/pull/1424

More information about the awt-dev mailing list