mirror of https://github.com/sbt/sbt.git
Merge pull request #6739 from adpi2/fix-cancel
Fix #6738: register all forked process
This commit is contained in:
commit
f70ef045b6
|
|
@ -18,7 +18,7 @@ import sbt.util.Logger
|
||||||
import sbt.ConcurrentRestrictions.Tag
|
import sbt.ConcurrentRestrictions.Tag
|
||||||
import sbt.protocol.testing._
|
import sbt.protocol.testing._
|
||||||
import sbt.internal.util.Util.{ AnyOps, none }
|
import sbt.internal.util.Util.{ AnyOps, none }
|
||||||
import sbt.internal.util.{ RunningProcesses, Terminal => UTerminal }
|
import sbt.internal.util.{ Terminal => UTerminal }
|
||||||
|
|
||||||
private[sbt] object ForkTests {
|
private[sbt] object ForkTests {
|
||||||
def apply(
|
def apply(
|
||||||
|
|
@ -158,13 +158,7 @@ private[sbt] object ForkTests {
|
||||||
classOf[ForkMain].getCanonicalName,
|
classOf[ForkMain].getCanonicalName,
|
||||||
server.getLocalPort.toString
|
server.getLocalPort.toString
|
||||||
)
|
)
|
||||||
val p = Fork.java.fork(fork, options)
|
val ec = Fork.java(fork, options)
|
||||||
RunningProcesses.add(p)
|
|
||||||
val ec = try p.exitValue()
|
|
||||||
finally {
|
|
||||||
if (p.isAlive()) p.destroy()
|
|
||||||
RunningProcesses.remove(p)
|
|
||||||
}
|
|
||||||
val result =
|
val result =
|
||||||
if (ec != 0)
|
if (ec != 0)
|
||||||
TestOutput(
|
TestOutput(
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,9 @@ package sbt
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.ProcessBuilder.Redirect
|
import java.lang.ProcessBuilder.Redirect
|
||||||
|
|
||||||
import scala.sys.process.Process
|
import scala.sys.process.Process
|
||||||
import OutputStrategy._
|
import OutputStrategy._
|
||||||
import sbt.internal.util.Util
|
import sbt.internal.util.{ RunningProcesses, Util }
|
||||||
import Util.{ AnyOps, none }
|
import Util.{ AnyOps, none }
|
||||||
|
|
||||||
import java.lang.{ ProcessBuilder => JProcessBuilder }
|
import java.lang.{ ProcessBuilder => JProcessBuilder }
|
||||||
|
|
@ -31,7 +30,15 @@ final class Fork(val commandName: String, val runnerClass: Option[String]) {
|
||||||
* It is configured according to `config`.
|
* It is configured according to `config`.
|
||||||
* If `runnerClass` is defined for this Fork instance, it is prepended to `arguments` to define the arguments passed to the forked command.
|
* If `runnerClass` is defined for this Fork instance, it is prepended to `arguments` to define the arguments passed to the forked command.
|
||||||
*/
|
*/
|
||||||
def apply(config: ForkOptions, arguments: Seq[String]): Int = fork(config, arguments).exitValue()
|
def apply(config: ForkOptions, arguments: Seq[String]): Int = {
|
||||||
|
val p = fork(config, arguments)
|
||||||
|
RunningProcesses.add(p)
|
||||||
|
try p.exitValue()
|
||||||
|
finally {
|
||||||
|
if (p.isAlive()) p.destroy()
|
||||||
|
RunningProcesses.remove(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forks the configured process and returns a `Process` that can be used to wait for completion or to terminate the forked process.
|
* Forks the configured process and returns a `Process` that can be used to wait for completion or to terminate the forked process.
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ package sbt
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.lang.reflect.Modifier.{ isPublic, isStatic }
|
import java.lang.reflect.Modifier.{ isPublic, isStatic }
|
||||||
|
|
||||||
import sbt.internal.inc.ScalaInstance
|
import sbt.internal.inc.ScalaInstance
|
||||||
import sbt.internal.inc.classpath.{ ClasspathFilter, ClasspathUtil }
|
import sbt.internal.inc.classpath.{ ClasspathFilter, ClasspathUtil }
|
||||||
import sbt.internal.util.MessageOnlyException
|
import sbt.internal.util.MessageOnlyException
|
||||||
|
|
@ -34,29 +33,40 @@ class ForkRun(config: ForkOptions) extends ScalaRun {
|
||||||
s"""Nonzero exit code returned from $label: $exitCode""".stripMargin
|
s"""Nonzero exit code returned from $label: $exitCode""".stripMargin
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val process = fork(mainClass, classpath, options, log)
|
|
||||||
def cancel() = {
|
log.info(s"running (fork) $mainClass ${Run.runOptionsStr(options)}")
|
||||||
log.warn("Run canceled.")
|
val c = configLogged(log)
|
||||||
process.destroy()
|
val scalaOpts = scalaOptions(mainClass, classpath, options)
|
||||||
1
|
val exitCode = try Fork.java(c, scalaOpts)
|
||||||
|
catch {
|
||||||
|
case _: InterruptedException =>
|
||||||
|
log.warn("Run canceled.")
|
||||||
|
1
|
||||||
}
|
}
|
||||||
val exitCode = try process.exitValue()
|
|
||||||
catch { case _: InterruptedException => cancel() }
|
|
||||||
processExitCode(exitCode, "runner")
|
processExitCode(exitCode, "runner")
|
||||||
}
|
}
|
||||||
|
|
||||||
def fork(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Process = {
|
def fork(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Process = {
|
||||||
log.info(s"running (fork) $mainClass ${Run.runOptionsStr(options)}")
|
log.info(s"running (fork) $mainClass ${Run.runOptionsStr(options)}")
|
||||||
|
|
||||||
val scalaOptions = classpathOption(classpath) ::: mainClass :: options.toList
|
val c = configLogged(log)
|
||||||
val configLogged =
|
val scalaOpts = scalaOptions(mainClass, classpath, options)
|
||||||
if (config.outputStrategy.isDefined) config
|
|
||||||
else config.withOutputStrategy(OutputStrategy.LoggedOutput(log))
|
|
||||||
// fork with Java because Scala introduces an extra class loader (#702)
|
// fork with Java because Scala introduces an extra class loader (#702)
|
||||||
Fork.java.fork(configLogged, scalaOptions)
|
Fork.java.fork(c, scalaOpts)
|
||||||
}
|
}
|
||||||
private def classpathOption(classpath: Seq[File]) =
|
|
||||||
"-classpath" :: Path.makeString(classpath) :: Nil
|
private def configLogged(log: Logger): ForkOptions = {
|
||||||
|
if (config.outputStrategy.isDefined) config
|
||||||
|
else config.withOutputStrategy(OutputStrategy.LoggedOutput(log))
|
||||||
|
}
|
||||||
|
|
||||||
|
private def scalaOptions(
|
||||||
|
mainClass: String,
|
||||||
|
classpath: Seq[File],
|
||||||
|
options: Seq[String]
|
||||||
|
): Seq[String] =
|
||||||
|
"-classpath" :: Path.makeString(classpath) :: mainClass :: options.toList
|
||||||
}
|
}
|
||||||
|
|
||||||
class Run(private[sbt] val newLoader: Seq[File] => ClassLoader, trapExit: Boolean)
|
class Run(private[sbt] val newLoader: Seq[File] => ClassLoader, trapExit: Boolean)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue