From ae12335bbb328f19b6b0ced83f7b53ce27b7b0cd Mon Sep 17 00:00:00 2001 From: Simeon Andreev Date: Sat, 6 Jun 2026 16:28:52 +0300 Subject: [PATCH] Fix race conditions in test ConsoleLineTracker Tests in org.eclipse.ant.tests.ui which rely on ConsoleLineTracker fail infrequently in I-builds. This is due to: 1. Relying on a boolean flag for more than two states. The flag indicates whether the last console is closed or not. An initialized console is marked as closed, which can confuse tests waiting on the closed console state. 2. Synchronizing on a transient object. When a console is initialized, the object used for synchronization is replaced. Tests may wait until timeout, due to notifyAll() calls on a different object. This change introduces a state enum and a single lock object, to avoid the race conditions. See: https://github.com/eclipse-platform/eclipse.platform/issues/2621 --- .../ui/testplugin/ConsoleLineTracker.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/ant/org.eclipse.ant.tests.ui/test plugin/org/eclipse/ant/tests/ui/testplugin/ConsoleLineTracker.java b/ant/org.eclipse.ant.tests.ui/test plugin/org/eclipse/ant/tests/ui/testplugin/ConsoleLineTracker.java index ac4ed4cf834..e2d37457b3b 100644 --- a/ant/org.eclipse.ant.tests.ui/test plugin/org/eclipse/ant/tests/ui/testplugin/ConsoleLineTracker.java +++ b/ant/org.eclipse.ant.tests.ui/test plugin/org/eclipse/ant/tests/ui/testplugin/ConsoleLineTracker.java @@ -27,22 +27,27 @@ */ public class ConsoleLineTracker implements IConsoleLineTrackerExtension { + private enum State { + UNINITIALIZED, INITIALIZED, CLOSED, DISPOSED, + } + + private static final Object LOCK = new Object(); private static IConsole console; private static List lines = new ArrayList<>(); - private static boolean consoleClosed = true; + private static State state = State.UNINITIALIZED; @Override public void dispose() { - // do nothing + state = State.DISPOSED; } @Override public void init(IConsole c) { - synchronized (lines) { + synchronized (LOCK) { ConsoleLineTracker.console = c; lines = new ArrayList<>(); - consoleClosed = false; + state = State.INITIALIZED; } } @@ -86,12 +91,12 @@ public static IDocument getDocument() { } public static void waitForConsole() { - synchronized (lines) { - if (consoleClosed) { + synchronized (LOCK) { + if (state == State.CLOSED) { return; } try { - lines.wait(20000); + LOCK.wait(20000); } catch (InterruptedException ie) { // do nothing @@ -101,15 +106,15 @@ public static void waitForConsole() { @Override public void consoleClosed() { - synchronized (lines) { - consoleClosed = true; + synchronized (LOCK) { + state = State.CLOSED; lines.notifyAll(); } } public static boolean isClosed() { - synchronized (lines) { - return consoleClosed; + synchronized (LOCK) { + return state == State.CLOSED; } } }