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.
-------------
Commit messages:
- Update SunToolkit.java
- The new tests
- Do not use shared state
- Update SunToolkit.java
- realSync too slow
- Update bug5074573.java
- Test update
- Initial fix
Changes: https://git.openjdk.java.net/jdk/pull/1424/files
Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=1424&range=00
Issue: https://bugs.openjdk.java.net/browse/JDK-8196100
Stats: 242 lines in 9 files changed: 192 ins; 20 del; 30 mod
Patch: https://git.openjdk.java.net/jdk/pull/1424.diff
Fetch: git fetch https://git.openjdk.java.net/jdk pull/1424/head:pull/1424
PR: https://git.openjdk.java.net/jdk/pull/1424