microsoft / microsoft/copilot-for-eclipse

Eclipse UI freezes during Copilot initialization while loading model preferences

Open
#297 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
126
Forks
60
Avg merge
2d 6h
Merged PRs (30d)
5

Description

Summary

Eclipse can freeze during Copilot UI initialization because model preference initialization synchronously waits for the Copilot language server persistence request on the SWT UI thread.

This was captured from a frozen Eclipse instance on macOS with Java 21. The UI thread stayed parked in the same stack across two thread dumps taken about one minute apart.

Impact

The Eclipse workbench UI becomes unresponsive during startup/initialization of the Copilot UI services.

Evidence from thread dump

The SWT UI thread is waiting on CompletableFuture.get() while loading user preferences:

"main" #1 ... java.lang.Thread.State: WAITING (parking)
  at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2072)
  at com.microsoft.copilot.eclipse.ui.chat.services.ChatBaseService.getPersistentFilePath(ChatBaseService.java:125)
  at com.microsoft.copilot.eclipse.ui.chat.services.ChatBaseService.getUserPreference(ChatBaseService.java:56)
  - locked <...> (a com.microsoft.copilot.eclipse.ui.chat.services.ModelService)
  at com.microsoft.copilot.eclipse.ui.chat.services.ModelService.lambda$0(ModelService.java:88)
  at com.microsoft.copilot.eclipse.ui.chat.services.ChatBaseService.lambda$1(ChatBaseService.java:111)
  at org.eclipse.ui.internal.PendingSyncExec.run(PendingSyncExec.java:68)
  at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4005)

The startup worker is waiting for that UI syncExec to complete:

"Worker-3: Copilot initialization" ... java.lang.Thread.State: TIMED_WAITING (parking)
  at org.eclipse.ui.internal.PendingSyncExec.waitUntilExecuted(PendingSyncExec.java:88)
  at org.eclipse.swt.widgets.Display.syncExec(Display.java:5264)
  at com.microsoft.copilot.eclipse.ui.utils.SwtUtils.invokeOnDisplayThread(SwtUtils.java:59)
  at com.microsoft.copilot.eclipse.ui.chat.services.ChatBaseService.ensureRealm(ChatBaseService.java:109)
  at com.microsoft.copilot.eclipse.ui.chat.services.ModelService.<init>(ModelService.java:84)
  at com.microsoft.copilot.eclipse.ui.chat.services.ChatServiceManager.<init>(ChatServiceManager.java:46)
  at com.microsoft.copilot.eclipse.ui.CopilotUi$1.run(CopilotUi.java:112)

The pending persistence request is blocked trying to write to the LSP JSON-RPC stream:

"LS-com.microsoft.copilot.eclipse.ls#dispatcher" ... java.lang.Thread.State: BLOCKED (on object monitor)
  at org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer.consume(StreamMessageConsumer.java:66)
  - waiting to lock <...> (a java.lang.Object)
  at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.request(RemoteEndpoint.java:171)
  at jdk.proxy16.$Proxy82.persistence(Unknown Source)
  at com.microsoft.copilot.eclipse.core.lsp.CopilotLanguageServerConnection.lambda$23(CopilotLanguageServerConnection.java:427)

That JSON-RPC output lock is held by a common-pool worker logging LSP traffic to the Eclipse console:

"ForkJoinPool.commonPool-worker-2" ... java.lang.Thread.State: RUNNABLE
  at org.eclipse.ui.internal.console.IOConsolePartitioner.helpProgress(IOConsolePartitioner.java:706)
  at org.eclipse.ui.console.MessageConsoleStream.println(MessageConsoleStream.java:99)
  at org.eclipse.lsp4e.LoggingStreamConnectionProviderProxy.logToConsole(LoggingStreamConnectionProviderProxy.java:276)
  at org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer.consume(StreamMessageConsumer.java:68)
  - locked <...> (a java.lang.Object)

No JVM-level deadlock marker was reported in the dumps, but this is still a UI freeze: the UI thread is synchronously waiting on an async LSP call, and that LSP call cannot proceed while the stream lock is held by console logging.

Suspected cause

ModelService constructs UI observables inside ensureRealm(...), and the initialization path calls getUserPreference(). That calls getPersistentFilePath(), which blocks on:

ChatPersistence chatPersistence = this.lsConnection.persistence().get();

Because this can run on the SWT UI thread, any delay or lock contention in the LSP request path freezes the workbench.

Suggested fix direction

Avoid blocking the SWT UI thread on lsConnection.persistence().get().

Possible approaches:

  • Load the persistence path asynchronously before reading preferences, then update observables when the result is available.
  • Initialize model preference observables with defaults and reconcile persisted preferences after lsConnection.persistence() completes.
  • Ensure getUserPreference() / getPersistentFilePath() are not called from UI-thread initialization paths if they need LSP I/O.
  • Consider whether LSP console logging should avoid holding the JSON-RPC output lock while writing to the Eclipse console, since that lock blocked the persistence request in the captured dump.

Environment from captured process

  • OS: macOS aarch64
  • Eclipse app: committers-2025-12/Eclipse.app
  • Java: JustJ OpenJDK 21.0.9
  • Frozen process command included -XstartOnFirstThread and -Dosgi.requiredJavaVersion=21

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.

Research direction

Start with ModelService.java, ChatBaseService.java, SwtUtils.java, and CopilotLanguageServerConnection.java, tracing ensureRealm(), getUserPreference(), and getPersistentFilePath(). Confirm the initialization path does not synchronously wait on lsConnection.persistence().get() from the SWT UI thread. Done means model preferences initialize without freezing the workbench while persisted values are reconciled when available.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.