mirror of https://github.com/sbt/sbt.git
Better error message if socket is taken
We need to communicate the error states in the thread, so I added a `Future[Unit]` called `ready`. If something goes wrong during the startup, like if the port is already taken, this can be used to communicate back to the main thread, and display the error accordingly.
This commit is contained in:
parent
6834def7b8
commit
0e8459ad66
|
|
@ -8,9 +8,13 @@ package server
|
|||
import java.net.{ SocketTimeoutException, InetAddress, ServerSocket, Socket }
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import sbt.util.Logger
|
||||
import sbt.internal.util.ErrorHandling
|
||||
import scala.concurrent.{ Future, Promise }
|
||||
import scala.util.{ Try, Success, Failure }
|
||||
|
||||
private[sbt] sealed trait ServerInstance {
|
||||
def shutdown(): Unit
|
||||
def ready: Future[Unit]
|
||||
}
|
||||
|
||||
private[sbt] object Server {
|
||||
|
|
@ -20,23 +24,31 @@ private[sbt] object Server {
|
|||
|
||||
// val lock = new AnyRef {}
|
||||
// val clients: mutable.ListBuffer[ClientConnection] = mutable.ListBuffer.empty
|
||||
val running = new AtomicBoolean(true)
|
||||
val running = new AtomicBoolean(false)
|
||||
val p: Promise[Unit] = Promise[Unit]()
|
||||
val ready: Future[Unit] = p.future
|
||||
|
||||
val serverThread = new Thread("sbt-socket-server") {
|
||||
|
||||
override def run(): Unit = {
|
||||
val serverSocket = new ServerSocket(port, 50, InetAddress.getByName(host))
|
||||
serverSocket.setSoTimeout(5000)
|
||||
|
||||
log.info(s"sbt server started at $host:$port")
|
||||
while (running.get()) {
|
||||
try {
|
||||
val socket = serverSocket.accept()
|
||||
onIncomingSocket(socket)
|
||||
} catch {
|
||||
case _: SocketTimeoutException => // its ok
|
||||
Try {
|
||||
ErrorHandling.translate(s"server failed to start on $host:$port. ") {
|
||||
new ServerSocket(port, 50, InetAddress.getByName(host))
|
||||
}
|
||||
|
||||
} match {
|
||||
case Failure(e) => p.failure(e)
|
||||
case Success(serverSocket) =>
|
||||
serverSocket.setSoTimeout(5000)
|
||||
log.info(s"sbt server started at $host:$port")
|
||||
running.set(true)
|
||||
p.success(())
|
||||
while (running.get()) {
|
||||
try {
|
||||
val socket = serverSocket.accept()
|
||||
onIncomingSocket(socket)
|
||||
} catch {
|
||||
case _: SocketTimeoutException => // its ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ import scala.annotation.tailrec
|
|||
import BasicKeys.serverPort
|
||||
import java.net.Socket
|
||||
import sjsonnew.JsonFormat
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.util.{ Success, Failure }
|
||||
|
||||
/**
|
||||
* The command exchange merges multiple command channels (e.g. network and console),
|
||||
|
|
@ -81,7 +84,15 @@ private[sbt] final class CommandExchange {
|
|||
server match {
|
||||
case Some(x) => // do nothing
|
||||
case _ =>
|
||||
server = Some(Server.start("127.0.0.1", port, onIncomingSocket, s.log))
|
||||
val x = Server.start("127.0.0.1", port, onIncomingSocket, s.log)
|
||||
Await.ready(x.ready, Duration("10s"))
|
||||
x.ready.value match {
|
||||
case Some(Success(_)) =>
|
||||
case Some(Failure(e)) =>
|
||||
s.log.error(e.toString)
|
||||
case None => // this won't happen because we awaited
|
||||
}
|
||||
server = Some(x)
|
||||
}
|
||||
s
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue