Skip to content

LSPDiagnosticsToMarkers causes invalid thread access exception on non-resource #1547

Description

@ahmedneilhussain

I'm in the process of rewriting our LSP4e-based eclipse integration and have run into an odd SWT threading violation from diagnostics publishing.

SWT.error(int, Throwable, String) line: 4920
  SWT.error(int, Throwable) line: 4833
  SWT.error(int) line: 4804
  CTabFolder(Widget).error(int) line: 811
  CTabFolder(Widget).checkWidget() line: 598
  ContributedPartRenderer$1(Widget).checkParent(Widget) line: 536
  ContributedPartRenderer$1(Widget).<init>(Widget, int) line: 142
  ContributedPartRenderer$1(Control).<init>(Composite, int) line: 124
  ContributedPartRenderer$1(Scrollable).<init>(Composite, int) line: 76
  ContributedPartRenderer$1(Composite).<init>(Composite, int) line: 96
  ContributedPartRenderer$1.<init>(ContributedPartRenderer, Composite, int, MPart) line: 86
  ContributedPartRenderer.createWidget(MUIElement, Object) line: 86
  PartRenderingEngine.createWidget(MUIElement, Object) line: 995
  PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 659
  PartRenderingEngine.safeCreateGui(MUIElement) line: 763
  PartRenderingEngine$2.run() line: 728
  SafeRunner.run(ISafeRunnable) line: 45
  PartRenderingEngine.createGui(MUIElement) line: 712
  PartServiceImpl.createElement(MUIElement) line: 1313
  PartServiceImpl.showPart(MPart, EPartService$PartState) line: 1274
  EditorReference(WorkbenchPartReference).getPart(boolean) line: 397
  EditorReference.getEditor(boolean) line: 283
  LSPDiagnosticsToMarkers.lambda$0(IEditorReference) line: 95
  0x00000008008cc6d8.apply(Object) line: not available
  ReferencePipeline$3$1.accept(P_OUT) line: 197
  HashMap$KeySpliterator<K,V>.forEachRemaining(Consumer<? super K>) line: 1707
  ReferencePipeline$3(AbstractPipeline<E_IN,E_OUT,S>).copyInto(Sink<P_IN>, Spliterator<P_IN>) line: 509
  ReferencePipeline$3(AbstractPipeline<E_IN,E_OUT,S>).wrapAndCopyInto(S, Spliterator<P_IN>) line: 499
  ForEachOps$ForEachOp$OfRef<T>(ForEachOps$ForEachOp<T>).evaluateSequential(PipelineHelper<T>, Spliterator<S>) line: 150
  ForEachOps$ForEachOp$OfRef<T>.evaluateSequential(PipelineHelper, Spliterator) line: 173
  ReferencePipeline$3(AbstractPipeline<E_IN,E_OUT,S>).evaluate(TerminalOp<E_OUT,R>) line: 234
  ReferencePipeline$3(ReferencePipeline<P_IN,P_OUT>).forEach(Consumer<? super P_OUT>) line: 596
  LSPDiagnosticsToMarkers.accept(PublishDiagnosticsParams) line: 101
  LSPDiagnosticsToMarkers.accept(Object) line: 1
  CocoLanguageClient(LanguageClientImpl).publishDiagnostics(PublishDiagnosticsParams) line: 101
  GeneratedMethodAccessor32.invoke(Object, Object[]) line: not available
  DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
  Method.invoke(Object, Object...) line: 568
  GenericEndpoint.lambda$recursiveFindRpcMethods$0(AnnotationUtil$MethodInfo, Object, Object) line: 65
  0x0000000800844a38.apply(Object) line: not available
  GenericEndpoint.notify(String, Object) line: 160
  RemoteEndpoint.handleNotification(NotificationMessage) line: 231
  RemoteEndpoint.consume(Message) line: 198
  LanguageServerWrapper.lambda$3(MessageConsumer, URI, Message) line: 313
  0x0000000800813af0.consume(Message) line: not available
  StreamMessageProducer.handleMessage(InputStream, StreamMessageProducer$Headers) line: 185
  StreamMessageProducer.listen(MessageConsumer) line: 97
  ConcurrentMessageProcessor.run() line: 114
  Executors$RunnableAdapter<T>.call() line: 539
  FutureTask<V>.run() line: 264
  ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1136
  ThreadPoolExecutor$Worker.run() line: 635
  Thread.run() line: 840

I get the problem when relaunching Eclipse on a workspace in a persisted state, with an editor for a file outside of a project.
The issue seems to be in the second branch of LSPDiagnosticsToMarkers.accept. I'm using an older version of LSP4e (0.18.11), but this code seems to be substantially unchanged other than a bit of non-semantic tidying up. The code has two branches, depending on whether the file targeted by a diagnostic is an IResource or not. It's the second branch that is causing the problem.

The scenario seems to be:

  • A file that the language server recognises, but which isn't part of a workspace project, is open as an editor in the workbench.
  • The file has a problem that the LS generates a marker for.
  • The workbench is restarted with the open editor as part of the persisted state.

There might be something racy about the issue as well - I know the normal branch will temporarily open editors if they're not already open to install markers. The editor in this case is clearly open in the workbench, but it might be that the diagnostics publishing sometimes runs before the editor has been materialised by the workbench restore.

Happy to contribute a fix but I'm not totally sure what the right fix might be. I have a workaround to override the LanguageClientImpl and make sure the diagnostics consumer runs via Display.getDefault().asyncExec(), but I'm not sure how robust that is.

Any Eclipse gurus able to help with the diagnosis?

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