summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-02-22 19:33:51 +0000
committerPaul Phillips <paulp@improving.org>2011-02-22 19:33:51 +0000
commit6961f663710ac4b61b4f6ef6dd3a34ff9ff7ca00 (patch)
treedf4466c3ba8a91f1be915b65f9eccb0591096551
parent8aaca8c135d6dcbc56b9bba92cd95ea5ea0a7e3c (diff)
downloadscala-6961f663710ac4b61b4f6ef6dd3a34ff9ff7ca00.tar.gz
scala-6961f663710ac4b61b4f6ef6dd3a34ff9ff7ca00.tar.bz2
scala-6961f663710ac4b61b4f6ef6dd3a34ff9ff7ca00.zip
Added daemonized() method to ProcessBuilder so ...
Added daemonized() method to ProcessBuilder so I can do things like start fsc without the jvm failing to exit. More logging to fsc. scala -e '5' now works again. Closes #4254, review by harrah.
-rw-r--r--src/compiler/scala/tools/nsc/CompileClient.scala13
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/CompileSocket.scala6
-rw-r--r--src/compiler/scala/tools/util/SocketServer.scala2
-rw-r--r--src/library/scala/sys/process/ProcessBuilder.scala6
-rw-r--r--src/library/scala/sys/process/ProcessBuilderImpl.scala14
-rw-r--r--src/library/scala/sys/process/ProcessIO.scala16
7 files changed, 43 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala
index 752e9a7930..d1b1f751ef 100644
--- a/src/compiler/scala/tools/nsc/CompileClient.scala
+++ b/src/compiler/scala/tools/nsc/CompileClient.scala
@@ -19,6 +19,10 @@ class StandardCompileClient extends HasCompileSocket {
val versionMsg = "Fast " + Properties.versionMsg
var verbose = false
+ def logVerbose(msg: String) =
+ if (verbose)
+ Console println msg
+
def main0(argsIn: Array[String]): Int = {
// TODO: put -J -and -D options back. Right now they are lost
// because bash parses them out and they don't arrive.
@@ -32,10 +36,11 @@ class StandardCompileClient extends HasCompileSocket {
Console println versionMsg
return 0
}
- if (verbose) {
- Console println fscArgs.mkString("[Given arguments: ", " ", "]")
- Console println vmArgs.mkString("[VM arguments: ", " ", "]")
- }
+
+ logVerbose(versionMsg)
+ logVerbose(fscArgs.mkString("[Given arguments: ", " ", "]"))
+ logVerbose(vmArgs.mkString("[VM arguments: ", " ", "]"))
+
val socket =
if (settings.server.value == "") compileSocket.getOrCreateSocket(vmArgs mkString " ", !shutdown)
else Some(compileSocket.getSocket(settings.server.value))
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index e33545d3c9..b6e9ab33d5 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -119,7 +119,8 @@ class StandardCompileServer extends SocketServer {
}
def isCompilerReusable: Boolean = {
if (compiler == null) {
- logVerbose("[Creating compiler instance for compile server.]")
+ logVerbose("[Creating new instance for compile server.]")
+ logVerbose("[Compiler version: " + Properties.versionString + ".]")
return false
}
val unequal = unequalSettings(command.settings, compiler.settings)
@@ -175,7 +176,6 @@ object CompileServer extends StandardCompileServer {
redirect(System.setErr, "scala-compile-server-err.log")
System.err.println("...starting server on socket "+port+"...")
System.err.flush()
-
compileSocket.setPort(port)
run()
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala
index 4f71a3da87..c75c6d0f22 100644
--- a/src/compiler/scala/tools/nsc/CompileSocket.scala
+++ b/src/compiler/scala/tools/nsc/CompileSocket.scala
@@ -110,7 +110,7 @@ class CompileSocket {
private def startNewServer(vmArgs: String) = {
val cmd = serverCommand(vmArgs split " " toSeq)
info("[Executing command: %s]" format cmd)
- cmd.run()
+ cmd.daemonized().run()
}
/** The port identification file */
@@ -132,8 +132,10 @@ class CompileSocket {
var attempts = 0
var port = pollPort()
- if (port < 0)
+ if (port < 0) {
+ info("No compile server running: starting one with args '" + vmArgs + "'")
startNewServer(vmArgs)
+ }
while (port < 0 && attempts < MaxAttempts) {
attempts += 1
diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala
index 57ebf96656..0094333402 100644
--- a/src/compiler/scala/tools/util/SocketServer.scala
+++ b/src/compiler/scala/tools/util/SocketServer.scala
@@ -40,7 +40,7 @@ abstract class SocketServer {
def fscIdleMillis = fscIdleMinutes * 60 * 1000
def shutdown: Boolean
- def session()
+ def session(): Unit
var out: PrintWriter = _
var in: BufferedReader = _
diff --git a/src/library/scala/sys/process/ProcessBuilder.scala b/src/library/scala/sys/process/ProcessBuilder.scala
index 0e34e7be1b..84a176b26d 100644
--- a/src/library/scala/sys/process/ProcessBuilder.scala
+++ b/src/library/scala/sys/process/ProcessBuilder.scala
@@ -81,6 +81,12 @@ trait ProcessBuilder extends Source with Sink {
* redirections (implemented as pipes) from masking useful process error codes.
*/
def hasExitValue: Boolean
+
+ /** Constructs a new builder which runs this command with all input/output threads marked
+ * as daemon threads. This allows the creation of a long running process while still
+ * allowing the JVM to exit normally.
+ */
+ def daemonized(): ProcessBuilder
}
object ProcessBuilder extends ProcessBuilderImpl {
diff --git a/src/library/scala/sys/process/ProcessBuilderImpl.scala b/src/library/scala/sys/process/ProcessBuilderImpl.scala
index adca575d4d..4f6d5211f3 100644
--- a/src/library/scala/sys/process/ProcessBuilderImpl.scala
+++ b/src/library/scala/sys/process/ProcessBuilderImpl.scala
@@ -18,6 +18,10 @@ import Uncloseable.protect
private[process] trait ProcessBuilderImpl {
self: ProcessBuilder.type =>
+ private[process] class DaemonBuilder(underlying: ProcessBuilder) extends AbstractBuilder {
+ final def run(io: ProcessIO): Process = underlying.run(io.daemonized())
+ }
+
private[process] class Dummy(override val toString: String, exitValue: => Int) extends AbstractBuilder {
override def run(io: ProcessIO): Process = new DummyProcess(exitValue)
override def canPipeTo = true
@@ -49,10 +53,10 @@ private[process] trait ProcessBuilderImpl {
override def run(io: ProcessIO): Process = {
val success = new SyncVar[Boolean]
success put false
- val t = Spawn {
+ val t = Spawn({
runImpl(io)
success set true
- }
+ }, io.daemonizeThreads)
new ThreadProcess(t, success)
}
@@ -66,10 +70,10 @@ private[process] trait ProcessBuilderImpl {
// spawn threads that process the input, output, and error streams using the functions defined in `io`
val inThread = Spawn(writeInput(process.getOutputStream), true)
- val outThread = Spawn(processOutput(process.getInputStream))
+ val outThread = Spawn(processOutput(process.getInputStream), daemonizeThreads)
val errorThread =
if (p.redirectErrorStream) Nil
- else List(Spawn(processError(process.getErrorStream)))
+ else List(Spawn(processError(process.getErrorStream), daemonizeThreads))
new SimpleProcess(process, inThread, outThread :: errorThread)
}
@@ -110,6 +114,8 @@ private[process] trait ProcessBuilderImpl {
def !< = run(true).exitValue()
def !<(log: ProcessLogger) = runBuffered(log, true)
+ def daemonized(): ProcessBuilder = new DaemonBuilder(this)
+
private[this] def slurp(log: Option[ProcessLogger], withIn: Boolean): String = {
val buffer = new StringBuffer
val code = this ! BasicIO(withIn, buffer, log)
diff --git a/src/library/scala/sys/process/ProcessIO.scala b/src/library/scala/sys/process/ProcessIO.scala
index 48ee91a11e..041cad1ef7 100644
--- a/src/library/scala/sys/process/ProcessIO.scala
+++ b/src/library/scala/sys/process/ProcessIO.scala
@@ -11,13 +11,19 @@ package process
import processInternal._
-/** Each method will be called in a separate thread.*/
+/** Each method will be called in a separate thread.
+ * If daemonizeThreads is true, they will all be marked daemon threads.
+ */
final class ProcessIO(
val writeInput: OutputStream => Unit,
val processOutput: InputStream => Unit,
- val processError: InputStream => Unit
+ val processError: InputStream => Unit,
+ val daemonizeThreads: Boolean
) {
- def withInput(write: OutputStream => Unit): ProcessIO = new ProcessIO(write, processOutput, processError)
- def withOutput(process: InputStream => Unit): ProcessIO = new ProcessIO(writeInput, process, processError)
- def withError(process: InputStream => Unit): ProcessIO = new ProcessIO(writeInput, processOutput, process)
+ def this(in: OutputStream => Unit, out: InputStream => Unit, err: InputStream => Unit) = this(in, out, err, false)
+
+ def withInput(write: OutputStream => Unit): ProcessIO = new ProcessIO(write, processOutput, processError, daemonizeThreads)
+ def withOutput(process: InputStream => Unit): ProcessIO = new ProcessIO(writeInput, process, processError, daemonizeThreads)
+ def withError(process: InputStream => Unit): ProcessIO = new ProcessIO(writeInput, processOutput, process, daemonizeThreads)
+ def daemonized(): ProcessIO = new ProcessIO(writeInput, processOutput, processError, true)
}