diff options
author | Paul Phillips <paulp@improving.org> | 2010-11-17 01:00:57 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-11-17 01:00:57 +0000 |
commit | 363a1456f671323b35dcacf2c8b8eb39180b8a53 (patch) | |
tree | 553913c9a121fa5595a95d40e59c5d9f6944d64c /src/compiler/scala/tools/util | |
parent | b7fcc7c73e41b326fe4d85d81c49c50fa954c990 (diff) | |
download | scala-363a1456f671323b35dcacf2c8b8eb39180b8a53.tar.gz scala-363a1456f671323b35dcacf2c8b8eb39180b8a53.tar.bz2 scala-363a1456f671323b35dcacf2c8b8eb39180b8a53.zip |
Two annoying REPL things made less annoying:
* ctrl-C will no longer kill the repl unless you hit it again
* ctrl-Z will no longer make the repl useless because of jline
In the service of the first I wrote signal handling code, which we can
put to use in other ways as well. No review.
Diffstat (limited to 'src/compiler/scala/tools/util')
-rw-r--r-- | src/compiler/scala/tools/util/SignalManager.scala | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/util/SignalManager.scala b/src/compiler/scala/tools/util/SignalManager.scala new file mode 100644 index 0000000000..a6513ecb50 --- /dev/null +++ b/src/compiler/scala/tools/util/SignalManager.scala @@ -0,0 +1,97 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2010 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools +package util + +import sun.misc.{ Signal, SignalHandler } +import SignalHandler._ +import nsc.io.timer + +/** Unofficial signal handling code. According to sun it's unsupported, + * but it's too useful not to take advantage of. Degrade gracefully. + */ +class SignalManager { + def apply(name: String): SignalWrapper = + try { new SignalWrapper(new Signal(name)) } + catch { case x: IllegalArgumentException => new SignalError(x.getMessage) } + + class ChainedHandler(prev: SignalHandler, current: SignalHandler) extends SignalHandler { + def handle(sig: Signal): Unit = { + current handle sig + if (prev != SIG_DFL && prev != SIG_IGN) + prev handle sig + } + } + class SignalWrapper(val signal: Signal) { + def name = signal.getName + def add(body: => Unit) = { + val handler = new SignalHandler { def handle(sig: Signal) = body } + val prev = Signal.handle(signal, handler) + + new ChainedHandler(prev, handler) + } + override def toString = "SIG" + name + } + class SignalError(message: String) extends SignalWrapper(null) { + override def toString = message + } +} + +object SignalManager extends SignalManager { + private implicit def mkSignalWrapper(name: String): SignalWrapper = this(name) + + def HUP: SignalWrapper = "HUP" + def INT: SignalWrapper = "INT" + def QUIT: SignalWrapper = "QUIT" + def ILL: SignalWrapper = "ILL" + def TRAP: SignalWrapper = "TRAP" + def ABRT: SignalWrapper = "ABRT" + def EMT: SignalWrapper = "EMT" + def FPE: SignalWrapper = "FPE" + def KILL: SignalWrapper = "KILL" + def BUS: SignalWrapper = "BUS" + def SEGV: SignalWrapper = "SEGV" + def SYS: SignalWrapper = "SYS" + def PIPE: SignalWrapper = "PIPE" + def ALRM: SignalWrapper = "ALRM" + def TERM: SignalWrapper = "TERM" + def URG: SignalWrapper = "URG" + def STOP: SignalWrapper = "STOP" + def TSTP: SignalWrapper = "TSTP" + def CONT: SignalWrapper = "CONT" + def CHLD: SignalWrapper = "CHLD" + def TTIN: SignalWrapper = "TTIN" + def TTOU: SignalWrapper = "TTOU" + def IO: SignalWrapper = "IO" + def XCPU: SignalWrapper = "XCPU" + def XFSZ: SignalWrapper = "XFSZ" + def VTALRM: SignalWrapper = "VTALRM" + def PROF: SignalWrapper = "PROF" + def WINCH: SignalWrapper = "WINCH" + def INFO: SignalWrapper = "INFO" + def USR1: SignalWrapper = "USR1" + def USR2: SignalWrapper = "USR2" + + /** Given a number of seconds, a signal, and a function: sets up a handler which upon + * receiving the signal once, calls the function with argument true, and if the + * signal is received again within the allowed time, calls it with argument false. + * (Otherwise it calls it with true and starts the timer over again.) + */ + def requireInterval(seconds: Int, wrapper: SignalWrapper)(fn: Boolean => Unit) = { + var received = false + wrapper add { + if (received) fn(false) + else { + received = true + fn(true) + timer(seconds)(received = false) + } + } + } +} + + + |