mirror of https://github.com/sbt/sbt.git
Fix watch for dumb terminals
On terminals with virtual io disabled, we'd spin up a thread for each watch iteration that performed a blocking read from the terminal input stream. This thread could not be joined which would cause the triggered execution to be delayed by 1 second while sbt blocked trying to join that thread. It also meant that input probably didn't work correctly since the user would end up with many threads polling from system in. The fix to this problem is to poll the terminal input stream if it is unsafe to do a blocking read, which is the case for dumb terminals or if virtual io is disabled.
This commit is contained in:
parent
c52e9916e2
commit
d52d413867
|
|
@ -327,6 +327,9 @@ object Terminal {
|
|||
if (isColorEnabled && doRed) Console.RED + str + Console.RESET
|
||||
else str
|
||||
|
||||
private[this] def hasVirtualIO = System.getProperty("sbt.io.virtual", "") == "true" || !isCI
|
||||
private[sbt] def canPollSystemIn: Boolean = hasConsole && !isDumbTerminal && hasVirtualIO
|
||||
|
||||
/**
|
||||
*
|
||||
* @param isServer toggles whether or not this is a server of client process
|
||||
|
|
@ -337,7 +340,7 @@ object Terminal {
|
|||
private[sbt] def withStreams[T](isServer: Boolean)(f: => T): T = {
|
||||
// In ci environments, don't touch the io streams unless run with -Dsbt.io.virtual=true
|
||||
if (hasConsole && !isDumbTerminal) consoleTerminalHolder.set(newConsoleTerminal())
|
||||
if (System.getProperty("sbt.io.virtual", "") == "true" || !isCI) {
|
||||
if (hasVirtualIO) {
|
||||
hasProgress.set(isServer && isAnsiSupported)
|
||||
activeTerminal.set(consoleTerminalHolder.get)
|
||||
try withOut(withIn(f))
|
||||
|
|
|
|||
|
|
@ -783,11 +783,20 @@ private[sbt] object Continuous extends DeprecatedContinuous {
|
|||
}
|
||||
executor => {
|
||||
val interrupted = new AtomicBoolean(false)
|
||||
@tailrec def read(): Int = {
|
||||
if (terminal.name.startsWith("network")) terminal.inputStream.read
|
||||
else if (Terminal.canPollSystemIn || terminal.inputStream.available > 0)
|
||||
terminal.inputStream.read
|
||||
else {
|
||||
Thread.sleep(50)
|
||||
read()
|
||||
}
|
||||
}
|
||||
@tailrec def impl(): Option[Watch.Action] = {
|
||||
val action =
|
||||
try {
|
||||
interrupted.set(false)
|
||||
terminal.inputStream.read match {
|
||||
read() match {
|
||||
case -1 => throw new InterruptedException
|
||||
case 3 => Watch.CancelWatch // ctrl+c on windows
|
||||
case byte => inputHandler(byte.toChar.toString)
|
||||
|
|
|
|||
Loading…
Reference in New Issue