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

Reply via email to