Skip to content

LSPDocumentAbstractHandler.setEnabled can cause an UI freeze #1331

@rubenporras

Description

@rubenporras

We have observed the following UI freeze caused by LSP4E:

!ENTRY org.eclipse.ui.monitoring 2 0 2025-07-21 10:01:26.475
!MESSAGE UI freeze of 0.36s at 10:01:26.097
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2025-07-21 10:01:26.475
!MESSAGE Sample at 10:01:26.298 (+0.201s)
Thread 'main' tid=1 (TIMED_WAITING)
!STACK 0
Stack Trace
	at [email protected]/jdk.internal.misc.Unsafe.park(Native Method)
	at [email protected]/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:252)
	at [email protected]/java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1866)
	at [email protected]/java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3463)
	at [email protected]/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3434)
	at [email protected]/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1939)
	at [email protected]/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2095)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor.matches(LSPDocumentAbstractHandler.java:69)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor.lambda$0(LSPDocumentAbstractHandler.java:59)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor$$Lambda$1693/0x0000000801a61638.test(Unknown Source)
	at [email protected]/java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90)
	at [email protected]/java.util.AbstractList$RandomAccessSpliterator.tryAdvance(AbstractList.java:706)
	at [email protected]/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at [email protected]/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at [email protected]/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at [email protected]/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at [email protected]/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
	at [email protected]/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
	at [email protected]/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at [email protected]/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:632)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler$LanguageServerDocumentHandlerExecutor.anyMatching(LSPDocumentAbstractHandler.java:59)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler.setEnabled(LSPDocumentAbstractHandler.java:123)
	at org.eclipse.lsp4e.internal.LSPDocumentAbstractHandler.setEnabled(LSPDocumentAbstractHandler.java:113)
	at org.eclipse.lsp4e.operations.rename.LSPRenameHandler.setEnabled(LSPRenameHandler.java:74)
	at org.eclipse.ui.internal.handlers.HandlerProxy.setEnabled(HandlerProxy.java:223)
	at org.eclipse.ui.internal.handlers.E4HandlerProxy.setEnabled(E4HandlerProxy.java:134)
	at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
	at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at [email protected]/java.lang.reflect.Method.invoke(Method.java:568)
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:299)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:233)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:174)
	at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.setEnabled(HandlerServiceHandler.java:91)
	at org.eclipse.core.commands.Command.setEnabled(Command.java:856)
	at org.eclipse.ui.menus.CommandContributionItem.isEnabled(CommandContributionItem.java:932)
	at org.eclipse.ui.menus.CommandContributionItem.updateMenuItem(CommandContributionItem.java:536)
	at org.eclipse.ui.menus.CommandContributionItem.update(CommandContributionItem.java:486)
	at org.eclipse.jface.action.MenuManager.update(MenuManager.java:857)
	at org.eclipse.jface.action.MenuManager.update(MenuManager.java:857)
	at org.eclipse.ui.internal.Workbench.updateActiveWorkbenchWindowMenuManager(Workbench.java:3246)
	at org.eclipse.ui.internal.Workbench.lambda$0(Workbench.java:3228)
	at org.eclipse.ui.internal.Workbench$$Lambda$397/0x0000000801196540.bindingManagerChanged(Unknown Source)
	at org.eclipse.jface.bindings.BindingManager.fireBindingManagerChanged(BindingManager.java:896)
	at org.eclipse.jface.bindings.BindingManager.setActiveBindings(BindingManager.java:2178)
	at org.eclipse.jface.bindings.BindingManager.recomputeBindings(BindingManager.java:1737)
	at org.eclipse.jface.bindings.BindingManager.contextManagerChanged(BindingManager.java:693)
	at org.eclipse.core.commands.contexts.ContextManager.fireContextManagerChanged(ContextManager.java:164)
	at org.eclipse.core.commands.contexts.ContextManager.setEventCaching(ContextManager.java:323)
	at org.eclipse.core.commands.contexts.ContextManager.deferUpdates(ContextManager.java:85)
	at org.eclipse.e4.ui.internal.workbench.PartServiceImpl.activate(PartServiceImpl.java:787)

Even though the handler waits for a max of 50ms, there are plenty of subclasses of LSPDocumentAbstractHandler, so calling setEnable on several of these these when opening/activating an editor (or starting the workbench) can cumulate to a noticeable UI freeze.

Since the code is prepared to return false and enable the handler asynchronously when the completableFuture finishes, I think we can eliminate the UI freeze by lowering the timeout to lower number, for example 5ms.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions