summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2008-10-22 09:46:19 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2008-10-22 09:46:19 +0000
commitc06b1d3f61f8d1bdf4d8ad58c97fec2c51e1e9f2 (patch)
treeab95adaea8cb03ee33b0e9a97a5a37cb186ca31d
parentf9924c9efdeb247b0ed330e70391aec0966555e9 (diff)
downloadscala-c06b1d3f61f8d1bdf4d8ad58c97fec2c51e1e9f2.tar.gz
scala-c06b1d3f61f8d1bdf4d8ad58c97fec2c51e1e9f2.tar.bz2
scala-c06b1d3f61f8d1bdf4d8ad58c97fec2c51e1e9f2.zip
fsc watchdog removal.
In addition, fixed a potential initialization problem in the fsc server, which would open a socket, get a port number, and close the socket, only to try to reallocate the same port number a bit later, even though the port might have become unavailable in the meantime. Now the socket is initialized only once, and the port is not released.
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala127
-rw-r--r--src/compiler/scala/tools/util/SocketServer.scala72
2 files changed, 97 insertions, 102 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index 541aadaffa..e652f8d6ec 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -35,8 +35,6 @@ class StandardCompileServer extends SocketServer {
var shutDown: Boolean = false
private var compiler: Global = null
- private var inSession: Boolean = false
- private var progress: Boolean = false
private def settingsAreCompatible(s1: Settings, s2: Settings) = s1 == s2
@@ -46,20 +44,6 @@ class StandardCompileServer extends SocketServer {
Predef.exit(code)
}
- private def spawnWatchDog(): Unit = spawn {
- while (true) {
- Thread.sleep(10000)
- if (!compileSocket.portFile(port).exists() && !inSession) {
- progress = false
- spawn {
- Thread.sleep(10000)
- if (!progress)
- fatal("port file no longer exists; exiting")
- }
- }
- }
- }
-
private val runtime = Runtime.getRuntime()
var reporter: ConsoleReporter = _
@@ -71,6 +55,10 @@ class StandardCompileServer extends SocketServer {
override def inform(msg: String) = out.println(msg)
}
+ override def timeout() {
+ if (!compileSocket.portFile(port).exists())
+ fatal("port file no longer exists; skipping cleanup")
+ }
protected def newOfflineCompilerCommand(
arguments: List[String],
@@ -89,68 +77,62 @@ class StandardCompileServer extends SocketServer {
val guessedPassword = in.readLine()
val input = in.readLine()
if ((input ne null) && password == guessedPassword) {
- try {
- inSession = true
- progress = true
- val args = input.split("\0",-1).toList
- if (args contains "-shutdown") {
- out.println("[Compile server exited]")
- shutDown = true
- return
- }
- if (args contains "-reset") {
- out.println("[Compile server was reset]")
- compiler = null
- return
- }
- def error(msg: String) {
- out.println(/*new Position*/ FakePos("fsc"),
- msg + "\n fsc -help gives more information")
- }
- val command = newOfflineCompilerCommand(args, new Settings(error), error, false)
-
- reporter = new ConsoleReporter(command.settings, in, out) {
- // disable prompts, so that compile server cannot block
- override def displayPrompt = ()
- }
-
- if (command.shouldStopWithInfo) {
- reporter.info(null,
- command.getInfoMessage(newGlobal(command.settings, reporter)), true)
+ val args = input.split("\0",-1).toList
+ if (args contains "-shutdown") {
+ out.println("[Compile server exited]")
+ shutDown = true
+ return
+ }
+ if (args contains "-reset") {
+ out.println("[Compile server was reset]")
+ compiler = null
+ return
+ }
+ def error(msg: String) {
+ out.println(/*new Position*/ FakePos("fsc"),
+ msg + "\n fsc -help gives more information")
+ }
+ val command = newOfflineCompilerCommand(args, new Settings(error), error, false)
+
+ reporter = new ConsoleReporter(command.settings, in, out) {
+ // disable prompts, so that compile server cannot block
+ override def displayPrompt = ()
+ }
+
+ if (command.shouldStopWithInfo) {
+ reporter.info(null,
+ command.getInfoMessage(newGlobal(command.settings, reporter)), true)
} else if (command.files.isEmpty)
- reporter.info(null, command.usageMsg, true)
- else {
- try {
- if ((compiler ne null) && settingsAreCompatible(command.settings, compiler.settings)) {
- compiler.settings = command.settings
- compiler.reporter = reporter
- } else {
- if (args contains "-verbose")
- out.println("[Starting new compile server instance]")
- compiler = newGlobal(command.settings, reporter)
- }
- val c = compiler
- val run = new c.Run
- run compile command.files
- } catch {
- case ex @ FatalError(msg) =>
- if (command.settings.debug.value)
- ex.printStackTrace(out);
+ reporter.info(null, command.usageMsg, true)
+ else {
+ try {
+ if ((compiler ne null) && settingsAreCompatible(command.settings, compiler.settings)) {
+ compiler.settings = command.settings
+ compiler.reporter = reporter
+ } else {
+ if (args contains "-verbose")
+ out.println("[Starting new compile server instance]")
+ compiler = newGlobal(command.settings, reporter)
+ }
+ val c = compiler
+ val run = new c.Run
+ run compile command.files
+ } catch {
+ case ex @ FatalError(msg) =>
+ if (command.settings.debug.value)
+ ex.printStackTrace(out);
reporter.error(null, "fatal error: " + msg)
compiler = null
- case ex: Throwable =>
- ex.printStackTrace(out);
+ case ex: Throwable =>
+ ex.printStackTrace(out);
reporter.error(null, "fatal error (server aborted): " + ex.getMessage())
shutDown = true
+ }
+ reporter.printSummary()
+ runtime.gc()
+ if ((runtime.totalMemory() - runtime.freeMemory()).toDouble /
+ runtime.maxMemory().toDouble > MaxCharge) compiler = null
}
- reporter.printSummary()
- runtime.gc()
- if ((runtime.totalMemory() - runtime.freeMemory()).toDouble /
- runtime.maxMemory().toDouble > MaxCharge) compiler = null
- }
- } finally {
- inSession = false
- }
}
}
@@ -171,7 +153,6 @@ class StandardCompileServer extends SocketServer {
redirect(System.setErr, "scala-compile-server-err.log")
System.err.println("...starting server on socket "+port+"...")
System.err.flush()
- spawnWatchDog()
compileSocket.setPort(port)
run()
compileSocket.deletePort(port)
diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala
index 3c311f1c53..486fe0e2b5 100644
--- a/src/compiler/scala/tools/util/SocketServer.scala
+++ b/src/compiler/scala/tools/util/SocketServer.scala
@@ -15,7 +15,7 @@ import java.io.PrintWriter
import java.io.BufferedOutputStream
import java.io.{BufferedReader, InputStreamReader}
import java.io.IOException
-import java.net.ServerSocket
+import java.net.{ServerSocket, SocketException, SocketTimeoutException}
/** The abstract class <code>SocketServer</code> implements the server
* communication for the fast Scala compiler.
@@ -36,46 +36,60 @@ abstract class SocketServer {
exit(1)
}
- val port: Int = try {
- val s = new ServerSocket(0) // a port of 0 creates a socket on any free port.
- val p = s.getLocalPort()
- s.close()
- p
+ private def warn(msg: String) {
+ System.err.println(msg)
+ }
+
+ // called after a timeout is detected,
+ // for SocketServer subclasses to perform
+ // some cleanup, if any
+ def timeout() {}
+
+ val serverSocket = try {
+ new ServerSocket(0)
} catch {
case e: IOException =>
fatal("Could not listen on any port; exiting.")
}
+ val port: Int = serverSocket.getLocalPort()
def run() {
- val serverSocket = try {
- new ServerSocket(port)
+ try {
+ // After 30 idle minutes, politely exit.
+ // Should the port file disappear, and the clients
+ // therefore unable to contact this server instance,
+ // the process will just eventually terminate by itself.
+ serverSocket.setSoTimeout(1800000)
} catch {
- case e: IOException =>
- fatal("Could not listen on port: " + port + "; exiting.")
+ case e: SocketException =>
+ fatal("Could not set timeout on port: " + port + "; exiting.")
}
- while (!shutDown) {
- val clientSocket = try {
- serverSocket.accept()
- } catch {
- case e: IOException =>
- fatal("Accept on port " + port + " failed; exiting.")
- }
+ try {
+ while (!shutDown) {
+ val clientSocket = try {
+ serverSocket.accept()
+ } catch {
+ case e: IOException =>
+ fatal("Accept on port " + port + " failed; exiting.")
+ }
- out = new PrintWriter(clientSocket.getOutputStream(), true)
- in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))
- val bufout = new BufferedOutputStream(clientSocket.getOutputStream, 10240)
+ out = new PrintWriter(clientSocket.getOutputStream(), true)
+ in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))
+ val bufout = new BufferedOutputStream(clientSocket.getOutputStream, 10240)
- scala.Console.withOut(bufout) {
- session()
+ scala.Console.withOut(bufout) {
+ session()
+ }
+ bufout.close()
+ out.close()
+ in.close()
+ clientSocket.close()
}
-
- bufout.close()
- out.close()
- in.close()
- clientSocket.close()
+ } catch {
+ case e: SocketTimeoutException =>
+ warn("Timeout elapsed with no requests from clients on port " + port + "; exiting")
+ timeout()
}
serverSocket.close()
}
-
}
-