@@ -2,7 +2,9 @@ package bloop.bsp
22
33import java .net .ServerSocket
44import java .net .Socket
5+ import java .nio .file .Files
56import java .nio .file .NoSuchFileException
7+ import java .nio .file .Path
68import java .util .concurrent .ConcurrentHashMap
79import java .util .concurrent .TimeUnit
810
@@ -32,6 +34,7 @@ object BspServer {
3234 private implicit val logContext : DebugFilter = DebugFilter .Bsp
3335
3436 import Commands .ValidatedBsp
37+
3538 private def initServer (handle : ServerHandle , state : State ): Task [ServerSocket ] = {
3639 state.logger.debug(s " Waiting for a connection at $handle... " )
3740 val openSocket = handle.server
@@ -52,10 +55,13 @@ object BspServer {
5255 ): Task [State ] = {
5356 import state .logger
5457
55- def listenToConnection (handle : ServerHandle , serverSocket : ServerSocket ): Task [State ] = {
58+ def listenToConnection (
59+ handle : ServerHandle ,
60+ serverSocket : ServerSocket ,
61+ shutdownHook : Option [Thread ]
62+ ): Task [State ] = {
5663 val isCommunicationActive = Atomic (true )
5764 val connectionURI = handle.uri
58-
5965 // Do NOT change this log, it's used by clients to know when to start a connection
6066 logger.info(s " The server is listening for incoming connections at $connectionURI... " )
6167 promiseWhenStarted.foreach(_.success(()))
@@ -122,11 +128,14 @@ object BspServer {
122128 case None => clients0
123129 }
124130 }
131+
125132 bspLogger.info {
126133 if (cancelled) " BSP server cancelled, closing socket..."
127134 else " BSP server stopped"
128135 }
136+
129137 server.cancelAllRequests()
138+
130139 ioScheduler.scheduleOnce(
131140 100 ,
132141 TimeUnit .MILLISECONDS ,
@@ -138,15 +147,25 @@ object BspServer {
138147 }
139148 }
140149 )
141- closeCommunication(latestState, socket, serverSocket)
150+
151+ val socketPath = handle match {
152+ case ServerHandle .UnixLocal (socketFile) => Some (socketFile.underlying)
153+ case _ => None
154+ }
155+
156+ shutdownHook.foreach { hook =>
157+ try Runtime .getRuntime.removeShutdownHook(hook)
158+ catch { case NonFatal (_) => () }
159+ }
160+
161+ closeCommunication(latestState, socket, serverSocket, socketPath)
142162 }
143163 }
144164
145165 process
146166 .doOnCancel(Task (stopListeting(cancelled = true )))
147167 .doOnFinish { errOpt =>
148- for (err <- errOpt)
149- err.printStackTrace(System .err)
168+ for (err <- errOpt) err.printStackTrace(System .err)
150169 Task (stopListeting(cancelled = false ))
151170 }
152171 .map(_ => provider.stateAfterExecution)
@@ -160,13 +179,27 @@ object BspServer {
160179 }
161180
162181 initServer(handle, state).materialize.flatMap {
163- case scala.util.Success (socket : ServerSocket ) =>
164- listenToConnection(handle, socket).onErrorRecover {
182+ case scala.util.Success (serverSocket : ServerSocket ) =>
183+ val shutdownHook : Option [Thread ] = handle match {
184+ case ServerHandle .UnixLocal (socketFile) =>
185+ val hook = new Thread {
186+ override def run (): Unit = {
187+ try Files .deleteIfExists(socketFile.underlying)
188+ catch { case NonFatal (_) => () }
189+ }
190+ }
191+ Runtime .getRuntime.addShutdownHook(hook)
192+ Some (hook)
193+ case _ => None
194+ }
195+
196+ listenToConnection(handle, serverSocket, shutdownHook).onErrorRecover {
165197 case t =>
166198 System .err.println(" Exiting BSP server with:" )
167199 t.printStackTrace(System .err)
168200 state.withError(s " Exiting BSP server with ${t.getMessage}" , t)
169201 }
202+
170203 case scala.util.Failure (t : Throwable ) =>
171204 promiseWhenStarted.foreach(p => if (! p.isCompleted) p.failure(t))
172205 Task .now(state.withError(s " BSP server failed to open a socket: ' ${t.getMessage}' " , t))
@@ -176,7 +209,8 @@ object BspServer {
176209 def closeCommunication (
177210 latestState : State ,
178211 socket : Socket ,
179- serverSocket : ServerSocket
212+ serverSocket : ServerSocket ,
213+ socketPath : Option [Path ] = None
180214 ): Unit = {
181215 // Close any socket communication asap and swallow exceptions
182216 try {
@@ -185,6 +219,12 @@ object BspServer {
185219 finally {
186220 try serverSocket.close()
187221 catch { case NonFatal (_) => () }
222+ finally {
223+ socketPath.foreach { path =>
224+ try Files .deleteIfExists(path)
225+ catch { case NonFatal (_) => () }
226+ }
227+ }
188228 }
189229 } finally {
190230 // Guarantee that we always schedule the external classes directories deletion
@@ -214,5 +254,4 @@ object BspServer {
214254 ()
215255 }
216256 }
217-
218257}
0 commit comments