summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala14
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineReader.scala5
-rw-r--r--src/compiler/scala/tools/nsc/io/package.scala14
3 files changed, 25 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 9c76fc2ff2..714853cdea 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -23,7 +23,7 @@ import scala.tools.nsc.util.{ ScalaClassLoader, Exceptional }
import ScalaClassLoader.URLClassLoader
import scala.util.control.Exception.{ Catcher, catching, catchingPromiscuously, ultimately, unwrapping }
-import io.{ PlainFile, VirtualDirectory, spawn }
+import io.{ PlainFile, VirtualDirectory, spawn, callable, newSingleThreadDaemonExecutor }
import reporters.{ ConsoleReporter, Reporter }
import symtab.{ Flags, Names }
import util.{ ScalaPrefs, JavaStackFrame, SourceFile, BatchSourceFile, ScriptSourceFile, ClassPath, Chars, stringFromWriter }
@@ -184,15 +184,17 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
}
}
+ /** An executor service which creates daemon threads. */
+ private lazy val lineExecutor = newSingleThreadDaemonExecutor()
private var currentExecution: Future[_] = null
private def sigintHandler = {
if (currentExecution == null) System.exit(1)
else currentExecution.cancel(true)
}
- /** Try to install sigint handler: ignore failure. */
- locally {
- try { SignalManager("INT") = sigintHandler }
- catch { case _: Exception => () }
+ /** Try to install sigint handler: false on failure. */
+ def installSigIntHandler(): Boolean = {
+ try { SignalManager("INT") = sigintHandler ; true }
+ catch { case _: Exception => false }
}
/** interpreter settings */
@@ -1016,7 +1018,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
catchingPromiscuously(onErr) {
unwrapping(wrapperExceptions: _*) {
/** Running it in a separate thread so it's easy to interrupt on ctrl-C. */
- val future = spawn(resultValMethod.invoke(loadedResultObject).toString)
+ val future = lineExecutor submit callable(resultValMethod.invoke(loadedResultObject).toString)
currentExecution = future
while (!future.isDone)
Thread.`yield`
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
index 032da9c395..e7c090db89 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
@@ -15,7 +15,10 @@ class JLineReader(interpreter: Interpreter) extends InteractiveReader {
override lazy val history = Some(History(consoleReader))
override lazy val completion = Option(interpreter) map (x => new Completion(x))
- override def init() = consoleReader.getTerminal().initializeTerminal()
+ override def init() = {
+ consoleReader.getTerminal().initializeTerminal()
+ interpreter.installSigIntHandler()
+ }
val consoleReader = {
val r = new jline.ConsoleReader()
diff --git a/src/compiler/scala/tools/nsc/io/package.scala b/src/compiler/scala/tools/nsc/io/package.scala
index 1d484a6c0e..8534e92f27 100644
--- a/src/compiler/scala/tools/nsc/io/package.scala
+++ b/src/compiler/scala/tools/nsc/io/package.scala
@@ -5,7 +5,7 @@
package scala.tools.nsc
-import java.util.concurrent.{ Future, Callable, Executors }
+import java.util.concurrent.{ Future, Callable, Executors, ThreadFactory }
import java.util.{ Timer, TimerTask }
package object io {
@@ -17,6 +17,18 @@ package object io {
def callableFn[T](f: () => T): Callable[T] = callable(f())
def spawnFn[T](f: () => T): Future[T] = spawn(f())
+ def newSingleThreadDaemonExecutor() = {
+ val factory = new ThreadFactory {
+ val default = Executors.defaultThreadFactory()
+ def newThread(r: Runnable) = {
+ val t = default.newThread(r)
+ t setDaemon true
+ t
+ }
+ }
+ Executors.newSingleThreadExecutor(factory)
+ }
+
// Create, start, and return a background thread
// If isDaemon is true, it is marked as daemon (and will not interfere with JVM shutdown)
def daemonize(isDaemon: Boolean)(body: => Unit): Thread = {