Skip to content

fix - UI freeze caused by deadlock in EditorsManager#183

Merged
jdneo merged 1 commit into
mainfrom
tori/fix-ui-freeze
May 13, 2026
Merged

fix - UI freeze caused by deadlock in EditorsManager#183
jdneo merged 1 commit into
mainfrom
tori/fix-ui-freeze

Conversation

@xinyi-gong
Copy link
Copy Markdown
Member

fix #175

Problem

The UI freezes on startup when a user closes an editor tab while Copilot is still initializing.

Deadlock chain:

  1. Worker thread calls getOrCreateNesRenderManager()ConcurrentHashMap.computeIfAbsent() holds an internal bucket lock → inside the lambda, new RenderManager()registerListeners()Display.syncExec() blocks waiting for UI thread
  2. UI thread handles editor close → disposeNesRenderManager()ConcurrentHashMap.remove() blocks waiting for the same bucket lock

Both threads wait on each other indefinitely → permanent UI freeze.

Fix

Replace computeIfAbsent() with get() + putIfAbsent() so that the RenderManager construction (which calls syncExec) happens outside of any map lock. If two threads race to create a manager for the same editor, the loser disposes its instance and uses the winner's.

Copilot AI review requested due to automatic review settings May 13, 2026 05:29
Copy link
Copy Markdown
Contributor

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 startup UI freeze caused by a deadlock between a worker thread creating a RenderManager (which performs Display.syncExec()) and the UI thread removing from the same ConcurrentHashMap bucket in EditorsManager.

Changes:

  • Replaced ConcurrentHashMap.computeIfAbsent() with get() + putIfAbsent() so RenderManager construction happens outside CHM’s internal bucket locks.
  • Added a contention path that disposes the “losing” RenderManager instance and returns the already-registered instance.
Comments suppressed due to low confidence (1)

com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/completion/EditorsManager.java:176

  • In the putIfAbsent contention path you dispose a freshly-created RenderManager. RenderManager currently subscribes to the Eclipse IEventBroker (NES accept/reject topics) but does not unsubscribe in dispose(), so a “losing” instance can keep receiving events for the same StyledText as the “winning” instance, causing duplicate accept/reject handling and memory leaks. Please ensure RenderManager.dispose() fully unregisters all listeners/subscriptions so disposing a losing instance is safe.
      mgr = new RenderManager(this.languageServer, this.nesProvider, editor);
      RenderManager existing = nesRenderManagers.putIfAbsent(editor, mgr);
      if (existing != null) {
        mgr.dispose();
        mgr = existing;

@jdneo jdneo merged commit c9e4ba4 into main May 13, 2026
8 checks passed
@jdneo jdneo deleted the tori/fix-ui-freeze branch May 13, 2026 06:48
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.

[Bug] UI freeze caused by deadlock in EditorsManager

3 participants