Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Orphaned event (EventQueue.dummyRunnable) in an eventQueue will break waitForIdle.

Open
#243 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
30/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
java

Research direction

Start with BasicRobot.waitForIdle and its windowMonitor.allEventQueues() handling, then inspect java.awt.EventQueue push/pop behavior around the supplied reproducer. Run the example with a hidden JFrame and custom EventQueue; done means waitForIdle returns promptly without treating an orphaned queue or dummyRunnable as pending work.

Written by the indexing model from the issue text.

Description

I've seen a sporadic failure where waitForIdle gets into a state where it times out after 10 seconds. The application is actually idle when this happens. This causes a lot of grief for us because it makes all the test run at a snails pace (20 minutes instead of 20 seconds).

2 important conditions for this failure:

  1. install a custom eventQueue via Toolkit.getDefaultToolkit().getSystemEventQueue().push()
  2. create and hide a Window first. (this is a splash screen in our real app).

After a lot of debugging by adding logs to BasicRobot waitForIdle, I manage to catch it where the custom event queue was empty, but it was waiting for a java.awt.EventQueue to drain. It contained an InvocationEvent with this runnable. "runnable=java.awt.EventQueue$1@2d1630f3". Looking into that lead me to the first anonymous class in EventQueue, which is the member variable "dummyRunnable". That dummyRunnable is used in push/pop to wake up the EDT.

I theorized that if the EDT was already awake when the new Queue was pushed, then that event could be left.

That didn't fail initially when I only had 1 window and tried the push from within an InvokeAndWait. I then expanded the test to create a window, hide it, push a new queue and then wait.

That reproduces the failure. Simple test case below. I think that the first queue (for the hidden window?) is really dead? maybe it should be removed from the "windowMonitor.allEventQueues()" in BasicRobot? I got this far, and now I'm at a loss as to how to proceed.

package ajs.eq.fail;

import java.awt.EventQueue;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import org.assertj.swing.core.BasicRobot;

public class AjsEqFail {

    private final static EventQueue myQueue = new EventQueue() {
        
    };
    public static void main(String[] args) {
        BasicRobot r = (BasicRobot) BasicRobot.robotWithCurrentAwtHierarchy();
        r.settings().simpleWaitForIdle(false);
        final JFrame f = new JFrame();
        f.setBounds(10,10,300,300);
        f.setVisible(true);
        r.waitForIdle();
        System.out.println("waited");
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println("Hi3");
                        }
                    });
                    System.out.println("Hi1");
                    f.setVisible(false);
                    Toolkit.getDefaultToolkit().getSystemEventQueue().push(myQueue);
                    JFrame f2 = new JFrame();
                    f2.setVisible(true);
                    f2.setBounds(10,10,300,300);
                    System.out.println("Hi2");
                }
            });
        } catch (InterruptedException ex) {
            Logger.getLogger(AjsEqFail.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(AjsEqFail.class.getName()).log(Level.SEVERE, null, ex);
        }
        r.waitForIdle(); //<-------------this times eventually (30 seconds?) but should be immediate.
        System.out.println("waited2");
    }
    
}

Dominant language
Java
Stars
121
Forks
52
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from assertj/assertj-swing

All issues in assertj/assertj-swing

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.