From bcad9f6887cb09e286670c0d0c7132395f6085b0 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 12 Jan 2025 01:30:12 -0500 Subject: [PATCH 1/2] fix: Fix run getting stuck **Problem** When the run ends too quickly it gets stuck. **Solution** This doesn't pause the channel if the job is already done. --- .../DefaultBackgroundJobService.scala | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/main/src/main/scala/sbt/internal/DefaultBackgroundJobService.scala b/main/src/main/scala/sbt/internal/DefaultBackgroundJobService.scala index 936fe9c57..0e1821488 100644 --- a/main/src/main/scala/sbt/internal/DefaultBackgroundJobService.scala +++ b/main/src/main/scala/sbt/internal/DefaultBackgroundJobService.scala @@ -28,6 +28,7 @@ import sbt.util.{ Level, Logger } import scala.concurrent.ExecutionContext import scala.concurrent.duration.* import scala.util.Try +import scala.util.control.NonFatal import sbt.util.LoggerContext import java.util.concurrent.TimeoutException import xsbti.FileConverter @@ -308,19 +309,21 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe copyClasspath(products, full, workingDirectory, hashFileContents = true, converter) private[sbt] def pauseChannelDuringJob(state: State, handle: JobHandle): Unit = - currentChannel(state) match - case Some(channel) => - handle match - case t: ThreadJobHandle => - val level = channel.logLevel - channel.setLevel(Level.Error) - channel.pause() - t.job.onStop: () => - channel.setLevel(level) - channel.resume() - channel.prompt(ConsolePromptEvent(state)) - case _ => () - case _ => () + if !jobs.contains(handle) then () + else + currentChannel(state) match + case Some(channel) => + handle match + case t: ThreadJobHandle => + val level = channel.logLevel + channel.setLevel(Level.Error) + channel.pause() + t.job.onStop: () => + channel.setLevel(level) + channel.resume() + channel.prompt(ConsolePromptEvent(state)) + case _ => () + case _ => () private[sbt] def currentChannel(state: State): Option[CommandChannel] = state.currentCommand match @@ -424,7 +427,8 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable { list } listeners.foreach { l => - l.executionContext.execute(() => l.callback()) + try l.executionContext.execute(() => l.callback()) + catch case NonFatal(_) => () } } } From cd090035838403d640155bc440e5708e28d5c7d7 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 12 Jan 2025 02:22:32 -0500 Subject: [PATCH 2/2] fix: Fix sbtn not showing run **Problem** Currently sbtn doesn't correctly display the stdout during `run` because by the time it starts the terminal has been reset. **Solution** Don't reset the terminal in-between the tasks. --- main/src/main/scala/sbt/MainLoop.scala | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index fd64f0530..4ae06128c 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -237,17 +237,16 @@ object MainLoop { exchange.setState(cmdProgressState) exchange.setExec(Some(exec)) - val (restoreTerminal, termState) = channelName.flatMap(exchange.channelForName) match { + val (flushTerminal, termState) = channelName.flatMap(exchange.channelForName) match case Some(c) => val prevTerminal = ITerminal.set(c.terminal) // temporarily set the prompt to running during task evaluation c.terminal.setPrompt(Prompt.Running) - (() => { - ITerminal.set(prevTerminal) - c.terminal.flush() - }) -> cmdProgressState.put(Keys.terminalKey, Terminal(c.terminal)) + (() => c.terminal.flush()) -> cmdProgressState.put( + Keys.terminalKey, + Terminal(c.terminal) + ) case _ => (() => ()) -> cmdProgressState.put(Keys.terminalKey, Terminal(ITerminal.get)) - } val currentCmdProgress = cmdProgressState.get(sbt.Keys.currentCommandProgress) @@ -283,12 +282,10 @@ object MainLoop { currentCmdProgress .foreach(_.afterCommand(exec.commandLine, Left(e))) throw e - } finally { + } finally // Flush the terminal output after command evaluation to ensure that all output - // is displayed in the thin client before we report the command status. Also - // set the prompt to whatever it was before we started evaluating the task. - restoreTerminal() - } + // is displayed in the thin client before we report the command status. + flushTerminal() if ( exec.execId.fold(true)(!_.startsWith(networkExecPrefix)) && !exec.commandLine.startsWith(networkExecPrefix)