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
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:The startup worker is waiting for that UI
syncExecto complete:The pending persistence request is blocked trying to write to the LSP JSON-RPC stream:
That JSON-RPC output lock is held by a common-pool worker logging LSP traffic to the Eclipse console:
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
ModelServiceconstructs UI observables insideensureRealm(...), and the initialization path callsgetUserPreference(). That callsgetPersistentFilePath(), which blocks on: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:
lsConnection.persistence()completes.getUserPreference()/getPersistentFilePath()are not called from UI-thread initialization paths if they need LSP I/O.Environment from captured process
committers-2025-12/Eclipse.app-XstartOnFirstThreadand-Dosgi.requiredJavaVersion=21