mirror of https://github.com/sbt/sbt.git
Catch ClosedChannelException in background job logger
We want the background job to stay alive even if its terminal has been closed and we cannot write to it anymore
This commit is contained in:
parent
592086b889
commit
634e8799e7
|
|
@ -126,11 +126,12 @@ object ConsoleAppender {
|
||||||
def out: ConsoleOut
|
def out: ConsoleOut
|
||||||
}
|
}
|
||||||
private[sbt] object Properties {
|
private[sbt] object Properties {
|
||||||
def from(terminal: Terminal): Properties = new Properties {
|
def from(terminal: Terminal): Properties =
|
||||||
override def isAnsiSupported: Boolean = terminal.isAnsiSupported
|
from(ConsoleOut.terminalOut(terminal), terminal.isAnsiSupported, terminal.isColorEnabled)
|
||||||
override def isColorEnabled: Boolean = terminal.isColorEnabled
|
|
||||||
override def out = ConsoleOut.terminalOut(terminal)
|
def safelyFrom(terminal: Terminal): Properties =
|
||||||
}
|
from(ConsoleOut.safeTerminalOut(terminal), terminal.isAnsiSupported, terminal.isColorEnabled)
|
||||||
|
|
||||||
def from(o: ConsoleOut, ansi: Boolean, color: Boolean): Properties = new Properties {
|
def from(o: ConsoleOut, ansi: Boolean, color: Boolean): Properties = new Properties {
|
||||||
override def isAnsiSupported: Boolean = ansi
|
override def isAnsiSupported: Boolean = ansi
|
||||||
override def isColorEnabled: Boolean = color
|
override def isColorEnabled: Boolean = color
|
||||||
|
|
@ -246,6 +247,18 @@ object ConsoleAppender {
|
||||||
new ConsoleAppender(name, Properties.from(terminal), noSuppressedMessage)
|
new ConsoleAppender(name, Properties.from(terminal), noSuppressedMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A new `ConsoleAppender` identified by `name`, and that writes to `terminal`.
|
||||||
|
* Printing to this Appender will not throw if the Terminal has been closed.
|
||||||
|
*
|
||||||
|
* @param name An identifier for the `ConsoleAppender`.
|
||||||
|
* @param terminal The terminal to which this appender corresponds
|
||||||
|
* @return A new `ConsoleAppender` that writes to `terminal`.
|
||||||
|
*/
|
||||||
|
def safe(name: String, terminal: Terminal): Appender = {
|
||||||
|
new ConsoleAppender(name, Properties.safelyFrom(terminal), noSuppressedMessage)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A new `ConsoleAppender` identified by `name`, and that writes to `out`.
|
* A new `ConsoleAppender` identified by `name`, and that writes to `out`.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
package sbt.internal.util
|
package sbt.internal.util
|
||||||
|
|
||||||
import java.io.{ BufferedWriter, PrintStream, PrintWriter }
|
import java.io.{ BufferedWriter, PrintStream, PrintWriter }
|
||||||
|
import java.nio.channels.ClosedChannelException
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
|
||||||
|
|
@ -90,6 +91,26 @@ object ConsoleOut {
|
||||||
override def toString: String = s"TerminalOut"
|
override def toString: String = s"TerminalOut"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Same as terminalOut but it catches and ignores the ClosedChannelException
|
||||||
|
*/
|
||||||
|
def safeTerminalOut(terminal: Terminal): ConsoleOut = {
|
||||||
|
val out = terminalOut(terminal)
|
||||||
|
new ConsoleOut {
|
||||||
|
override val lockObject: AnyRef = terminal
|
||||||
|
override def print(s: String): Unit = catchException(out.print(s))
|
||||||
|
override def println(s: String): Unit = catchException(out.println(s))
|
||||||
|
override def println(): Unit = catchException(out.println())
|
||||||
|
override def flush(): Unit = catchException(out.flush)
|
||||||
|
override def toString: String = s"SafeTerminalOut($terminal)"
|
||||||
|
private def catchException(f: => Unit): Unit = {
|
||||||
|
try f
|
||||||
|
catch {
|
||||||
|
case _: ClosedChannelException => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private[this] val consoleOutPerTerminal = new ConcurrentHashMap[Terminal, ConsoleOut]
|
private[this] val consoleOutPerTerminal = new ConcurrentHashMap[Terminal, ConsoleOut]
|
||||||
def terminalOut(terminal: Terminal): ConsoleOut = consoleOutPerTerminal.get(terminal) match {
|
def terminalOut(terminal: Terminal): ConsoleOut = consoleOutPerTerminal.get(terminal) match {
|
||||||
case null =>
|
case null =>
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ object LogManager {
|
||||||
task: ScopedKey[_],
|
task: ScopedKey[_],
|
||||||
context: LoggerContext
|
context: LoggerContext
|
||||||
): ManagedLogger = {
|
): ManagedLogger = {
|
||||||
val console = ConsoleAppender("bg-" + ConsoleAppender.generateName(), ITerminal.current)
|
val console = ConsoleAppender.safe("bg-" + ConsoleAppender.generateName(), ITerminal.current)
|
||||||
LogManager.backgroundLog(data, state, task, console, relay(()), context)
|
LogManager.backgroundLog(data, state, task, console, relay(()), context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue