From 10c549a0b950db55eb9bf9cb90cef92c393282f8 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Tue, 6 Oct 2020 07:17:16 -0700 Subject: [PATCH] Fix sbt hangs with invalid build.sbt and --batch When sbt is starting up and there is an error with the build loading, we need to read input from the user to determine to restart the build or not. What is tricky is that there are potentially two sources of input: thin clients connected through the boot server socket and the actual sbt console process. If there are not connected thin clients and no system console is available, we should return -1 in System.in.read, which will cause sbt to exit. --- .../src/main/scala/sbt/internal/util/Terminal.scala | 6 ++++++ .../src/main/java/sbt/internal/BootServerSocket.java | 1 + 2 files changed, 7 insertions(+) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala index 829b2f3cb..e28f0ea54 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala @@ -179,6 +179,7 @@ trait Terminal extends AutoCloseable { } object Terminal { + val NO_BOOT_CLIENTS_CONNECTED: Int = -2 // Disable noisy jline log spam if (System.getProperty("sbt.jline.verbose", "false") != "true") jline.internal.Log.setOutput(new PrintStream(_ => {}, false)) @@ -618,6 +619,11 @@ object Terminal { if (running.get) { inputStream.read match { case -1 => + case `NO_BOOT_CLIENTS_CONNECTED` => + if (System.console == null) { + result.put(-1) + running.set(false) + } case i => result.put(i) running.set(false) diff --git a/main-command/src/main/java/sbt/internal/BootServerSocket.java b/main-command/src/main/java/sbt/internal/BootServerSocket.java index b153f32f9..3cda9e830 100644 --- a/main-command/src/main/java/sbt/internal/BootServerSocket.java +++ b/main-command/src/main/java/sbt/internal/BootServerSocket.java @@ -216,6 +216,7 @@ public class BootServerSocket implements AutoCloseable { new InputStream() { @Override public int read() { + if (clientSockets.isEmpty()) return Terminal.NO_BOOT_CLIENTS_CONNECTED(); try { synchronized (needInput) { needInput.set(true);