eclipse-lsp4e / eclipse-lsp4e/lsp4e

LanguageServerWrapper is not stopped on Eclipse shutdown

Open
#681 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
85
Forks
69
Avg merge
8h 33m
Merged PRs (30d)
6

Description

Eclipse outputs the following error to standard error on shutdown, if any LSP-enabled editors are still opened:

Jun 04, 2023 8:12:12 PM org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer fireStreamClosed
INFO: The input stream was closed.
java.io.InterruptedIOException
	at java.base/java.io.PipedInputStream.read(PipedInputStream.java:328)
	at org.vgcpge.eclipse.copilot.ui.internal.OrphanPipedInputStream.read(OrphanPipedInputStream.java:21)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:79)
	at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)

The problem is caused by interruption of the MessageProducer on shutdown.

Thread [Framework stop - Equinox Container: e7e68fc9-1058-4290-853a-605fd888929e] (Suspended (breakpoint at line 670 in ThreadPoolExecutor$Worker))	
	owns: Object  (id=178)	
	ThreadPoolExecutor$Worker.interruptIfStarted() line: 670	
	ThreadPoolExecutor.interruptWorkers() line: 769	
	ThreadPoolExecutor.shutdownNow() line: 1417	
	LanguageServerWrapper.stopDispatcher() line: 210	
	0x00000008013a7440.accept(Object) line: not available	
	CopyOnWriteArrayList<E>.forEach(Consumer<? super E>) line: 807	
	CopyOnWriteArraySet<E>.forEach(Consumer<? super E>) line: 425	
	LanguageServiceAccessor.shutdownAllDispatchers() line: 686	
	LanguageServerPlugin.stop(BundleContext) line: 43	
	BundleContextImpl$3.run() line: 875	
	BundleContextImpl$3.run() line: 1	
	AccessController.executePrivileged(PrivilegedExceptionAction<T>, AccessControlContext, Class<?>) line: 807	
	AccessController.doPrivileged(PrivilegedExceptionAction<T>) line: 569	
	BundleContextImpl.stop() line: 867	
	EquinoxBundle.stopWorker0() line: 1046	
	EquinoxBundle$EquinoxModule.stopWorker() line: 376	
	EquinoxBundle$EquinoxModule(Module).doStop() line: 660	
	EquinoxBundle$EquinoxModule(Module).stop(Module$StopOptions...) line: 521	
	ModuleContainer$ContainerStartLevel.decStartLevel(int, List<Module>) line: 1893	
	ModuleContainer$ContainerStartLevel.doContainerStartLevel(Module, int, FrameworkListener...) line: 1768	
	EquinoxBundle$SystemBundle$EquinoxSystemModule(SystemModule).stopWorker() line: 275	
	EquinoxBundle$SystemBundle$EquinoxSystemModule.stopWorker() line: 208	
	EquinoxBundle$SystemBundle$EquinoxSystemModule(Module).doStop() line: 660	
	EquinoxBundle$SystemBundle$EquinoxSystemModule(Module).stop(Module$StopOptions...) line: 521	
	EquinoxBundle$SystemBundle$EquinoxSystemModule(SystemModule).stop(Module$StopOptions...) line: 207	
	EquinoxBundle$SystemBundle$EquinoxSystemModule$1.run() line: 226	
	Thread.run() line: 833	

Investigation shows, that LSP4E relies on LanguageServerWrapper to stop processing before its Executor is shutdown. However, the only way to stop processing is to call LanguageServerWrapper.stop() and that is not called on shutdown - the call is delayed too much by org.eclipse.lsp4e.LanguageServerWrapper.startStopTimer().

AFAIK, this results in forceful termination of child process without a chance for graceful shutdown.

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 LanguageServerWrapper.stop(), stopDispatcher(), and startStopTimer(), then trace LanguageServiceAccessor.shutdownAllDispatchers() and LanguageServerPlugin.stop() to understand the shutdown ordering. Confirm that dispatchers stop processing before their executor is shut down, that the child process can shut down gracefully, and that Eclipse no longer emits the reported InterruptedIOException.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.