eclipse-lsp4j / lsp4j

A Java implementation of the language server protocol intended to be consumed by tools and language servers implemented in Java.
https://eclipse.org/lsp4j
Other
613 stars 145 forks source link

JSON-RPC how to close the connection without logging #585

Closed frankbenoit closed 2 years ago

frankbenoit commented 2 years ago

Hi,

I see these loggings:

org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer fireStreamClosed
[2021-12-21T20:08:45.021Z] INFO: Socket closed
[2021-12-21T20:08:45.021Z] java.net.SocketException: Socket closed
[2021-12-21T20:08:45.021Z]  at java.base/sun.nio.ch.NioSocketImpl.endRead(NioSocketImpl.java:248)
[2021-12-21T20:08:45.021Z]  at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:327)
[2021-12-21T20:08:45.021Z]  at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350)
[2021-12-21T20:08:45.021Z]  at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803)
[2021-12-21T20:08:45.021Z]  at java.base/java.net.Socket$SocketInputStream.read(Socket.java:981)
[2021-12-21T20:08:45.021Z]  at java.base/java.net.Socket$SocketInputStream.read(Socket.java:976)
[2021-12-21T20:08:45.021Z]  at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:79)
[2021-12-21T20:08:45.021Z]  at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
[2021-12-21T20:08:45.021Z]  at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[2021-12-21T20:08:45.021Z]  at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[2021-12-21T20:08:45.021Z]  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
[2021-12-21T20:08:45.021Z]  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
[2021-12-21T20:08:45.021Z]  at java.base/java.lang.Thread.run(Thread.java:832)

Those are in general OK, but they should not be there when a connection is shut down intentionally. Now I wonder how to shut down correctly. ATM I do a socket.close() and I call the cancel of the Future that is returned by the Launcher.startListening.

From the sources, I think the StreamMessageProducer.close() should be called somehow, to avoid the logging in the shutdown case. But the instance of StreamMessageProducer is not accessible and its close() seems nowhere be called.

Is it a bug? Is there another procedure to shut down a Launcher correctly?

Frank

pisv commented 2 years ago

Hi Frank,

ATM I do a socket.close() and I call the cancel of the Future that is returned by the Launcher.startListening.

I think this socket.close() is the culprit here. Just call cancel(true) on the future and everything should be OK.

From the sources, I think the StreamMessageProducer.close() should be called somehow, to avoid the logging in the shutdown case. But the instance of StreamMessageProducer is not accessible and its close() seems nowhere be called.

The close() is called at ConcurrentMessageProcessor, line 72 (when the wrapping future is canceled with mayInterruptIfRunning == true).

HTH

frankbenoit commented 2 years ago

Thanks, i missed that one