Skip to content

Comments

Don't use display thread for scheduling console update tasks#2461

Open
iloveeclipse wants to merge 1 commit intoeclipse-platform:masterfrom
iloveeclipse:issue_2460
Open

Don't use display thread for scheduling console update tasks#2461
iloveeclipse wants to merge 1 commit intoeclipse-platform:masterfrom
iloveeclipse:issue_2460

Conversation

@iloveeclipse
Copy link
Member

This fixes regression from 7e1f60c, where main thread (which owns lock on UI operations) waits for the lock on ProcessConsole to update console name but never gets it because console code is blocked internally waiting for a QueueProcessingJob being executed on UI thread.

The solution is to avoid direct calls from UI to ProcessConsole.resetName().

Fixes #2460

This fixes regression from 7e1f60c, where main thread (which owns lock
on UI operations) waits for the lock on ProcessConsole to update console
name but never gets it because console code is blocked internally
waiting for a QueueProcessingJob being executed on UI thread.

The solution is to avoid direct calls from UI to
ProcessConsole.resetName().

Fixes eclipse-platform#2460
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a deadlock issue (#2460) that occurred when terminating launches. The deadlock happened because the UI thread would wait for a lock on ProcessConsole to update the console name, while console code was blocked waiting for a QueueProcessingJob to execute on the same UI thread. The fix introduces a separate ScheduledExecutorService to handle console name updates asynchronously, avoiding direct calls from the UI thread to ProcessConsole.resetName().

Changes:

  • Replaced UI thread timer-based scheduling (Display.timerExec) with a dedicated ScheduledExecutorService for console name updates
  • Added proper executor cleanup in the dispose() method
  • Introduced tracking of pending name update tasks to avoid duplicate scheduling

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +366 to +370
currentPending = consoleNameUpdateExecutor.schedule(() -> {
pendingNameUpdate = null;
resetName(false);
}, 1, TimeUnit.SECONDS);
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assignment currentPending = consoleNameUpdateExecutor.schedule(...) on line 366 updates the local variable but does not update the instance field pendingNameUpdate. This means the check on line 365 (currentPending == null || currentPending.isDone()) will always evaluate to true after the first scheduling, potentially causing multiple concurrent scheduled tasks instead of preventing them. The result of schedule() should be assigned to pendingNameUpdate to properly track the scheduled future.

Copilot uses AI. Check for mistakes.
Comment on lines +364 to +369
ScheduledFuture<?> currentPending = pendingNameUpdate;
if (currentPending == null || currentPending.isDone()) {
currentPending = consoleNameUpdateExecutor.schedule(() -> {
pendingNameUpdate = null;
resetName(false);
}, 1, TimeUnit.SECONDS);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The read of pendingNameUpdate on line 364 and the potential write on line 367 are not properly synchronized, which can lead to race conditions in a multi-threaded environment. Multiple threads calling computeName() concurrently could read pendingNameUpdate as null simultaneously, causing multiple tasks to be scheduled despite the intent to schedule only one. Consider using AtomicReference for pendingNameUpdate or adding proper synchronization around this check-and-set pattern.

Suggested change
ScheduledFuture<?> currentPending = pendingNameUpdate;
if (currentPending == null || currentPending.isDone()) {
currentPending = consoleNameUpdateExecutor.schedule(() -> {
pendingNameUpdate = null;
resetName(false);
}, 1, TimeUnit.SECONDS);
synchronized (this) {
ScheduledFuture<?> currentPending = pendingNameUpdate;
if (currentPending == null || currentPending.isDone()) {
pendingNameUpdate = consoleNameUpdateExecutor.schedule(() -> {
synchronized (ProcessConsole.this) {
pendingNameUpdate = null;
resetName(false);
}
}, 1, TimeUnit.SECONDS);
}

Copilot uses AI. Check for mistakes.
@@ -531,6 +547,7 @@ public IProcess getProcess() {
protected void dispose() {
super.dispose();
fColorProvider.disconnect();
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the console is disposed, shutdownNow() is called on line 550, which will attempt to stop all actively executing tasks. However, if a scheduled task is in the middle of calling resetName(false), it could encounter errors since the console may be in an inconsistent state during disposal. Consider canceling the pendingNameUpdate task explicitly before calling shutdownNow(), or check if the console is being disposed at the start of the scheduled task.

Suggested change
fColorProvider.disconnect();
fColorProvider.disconnect();
if (pendingNameUpdate != null) {
pendingNameUpdate.cancel(false);
}

Copilot uses AI. Check for mistakes.
@iloveeclipse
Copy link
Member Author

@trancexpress : if you can reproduce, please try this PR.

Beside this, I wonder if this task that updates console every second must be always executed, even if console is hidden behind other one. This is definitely a resource waste. Start ~6 processes with Console and enjoy that every 100 ms some task is executed updating some of the consoles.

This makes no sense. So probably the code has to be rewritten to avoid parallel updates of hidden console pages.

@trancexpress
Copy link
Contributor

I wasn't able to reproduce the deadlock when I tried. Likely it needs stepping with breakpoints, I've not checked how to do that.

@github-actions
Copy link
Contributor

Test Results

 1 977 files  + 27   1 977 suites  +27   1h 35m 52s ⏱️ + 5m 49s
 4 743 tests ±  0   4 719 ✅ +  1   24 💤 ±0  0 ❌  - 1 
14 229 runs  +153  14 047 ✅ +154  182 💤 ±0  0 ❌  - 1 

Results for commit 16c60c8. ± Comparison against base commit 8594fad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deadlock on terminating launch

2 participants