Skip to content

Commit c1d20f5

Browse files
committed
Fix sbt#6738: register all forked process
1 parent fb5f0a8 commit c1d20f5

File tree

3 files changed

+37
-26
lines changed

3 files changed

+37
-26
lines changed

main-actions/src/main/scala/sbt/ForkTests.scala

+2-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import sbt.util.Logger
1818
import sbt.ConcurrentRestrictions.Tag
1919
import sbt.protocol.testing._
2020
import sbt.internal.util.Util.{ AnyOps, none }
21-
import sbt.internal.util.{ RunningProcesses, Terminal => UTerminal }
21+
import sbt.internal.util.{ Terminal => UTerminal }
2222

2323
private[sbt] object ForkTests {
2424
def apply(
@@ -158,13 +158,7 @@ private[sbt] object ForkTests {
158158
classOf[ForkMain].getCanonicalName,
159159
server.getLocalPort.toString
160160
)
161-
val p = Fork.java.fork(fork, options)
162-
RunningProcesses.add(p)
163-
val ec = try p.exitValue()
164-
finally {
165-
if (p.isAlive()) p.destroy()
166-
RunningProcesses.remove(p)
167-
}
161+
val ec = Fork.java(fork, options)
168162
val result =
169163
if (ec != 0)
170164
TestOutput(

run/src/main/scala/sbt/Fork.scala

+10-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ package sbt
99

1010
import java.io.File
1111
import java.lang.ProcessBuilder.Redirect
12-
1312
import scala.sys.process.Process
1413
import OutputStrategy._
15-
import sbt.internal.util.Util
14+
import sbt.internal.util.{ RunningProcesses, Util }
1615
import Util.{ AnyOps, none }
1716

1817
import java.lang.{ ProcessBuilder => JProcessBuilder }
@@ -31,7 +30,15 @@ final class Fork(val commandName: String, val runnerClass: Option[String]) {
3130
* It is configured according to `config`.
3231
* If `runnerClass` is defined for this Fork instance, it is prepended to `arguments` to define the arguments passed to the forked command.
3332
*/
34-
def apply(config: ForkOptions, arguments: Seq[String]): Int = fork(config, arguments).exitValue()
33+
def apply(config: ForkOptions, arguments: Seq[String]): Int = {
34+
val p = fork(config, arguments)
35+
RunningProcesses.add(p)
36+
try p.exitValue()
37+
finally {
38+
if (p.isAlive()) p.destroy()
39+
RunningProcesses.remove(p)
40+
}
41+
}
3542

3643
/**
3744
* Forks the configured process and returns a `Process` that can be used to wait for completion or to terminate the forked process.

run/src/main/scala/sbt/Run.scala

+25-15
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ package sbt
1010
import java.io.File
1111
import java.lang.reflect.Method
1212
import java.lang.reflect.Modifier.{ isPublic, isStatic }
13-
1413
import sbt.internal.inc.ScalaInstance
1514
import sbt.internal.inc.classpath.{ ClasspathFilter, ClasspathUtil }
1615
import sbt.internal.util.MessageOnlyException
@@ -34,29 +33,40 @@ class ForkRun(config: ForkOptions) extends ScalaRun {
3433
s"""Nonzero exit code returned from $label: $exitCode""".stripMargin
3534
)
3635
)
37-
val process = fork(mainClass, classpath, options, log)
38-
def cancel() = {
39-
log.warn("Run canceled.")
40-
process.destroy()
41-
1
36+
37+
log.info(s"running (fork) $mainClass ${Run.runOptionsStr(options)}")
38+
val c = configLogged(log)
39+
val scalaOpts = scalaOptions(mainClass, classpath, options)
40+
val exitCode = try Fork.java(c, scalaOpts)
41+
catch {
42+
case _: InterruptedException =>
43+
log.warn("Run canceled.")
44+
1
4245
}
43-
val exitCode = try process.exitValue()
44-
catch { case _: InterruptedException => cancel() }
4546
processExitCode(exitCode, "runner")
4647
}
4748

4849
def fork(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Process = {
4950
log.info(s"running (fork) $mainClass ${Run.runOptionsStr(options)}")
5051

51-
val scalaOptions = classpathOption(classpath) ::: mainClass :: options.toList
52-
val configLogged =
53-
if (config.outputStrategy.isDefined) config
54-
else config.withOutputStrategy(OutputStrategy.LoggedOutput(log))
52+
val c = configLogged(log)
53+
val scalaOpts = scalaOptions(mainClass, classpath, options)
54+
5555
// fork with Java because Scala introduces an extra class loader (#702)
56-
Fork.java.fork(configLogged, scalaOptions)
56+
Fork.java.fork(c, scalaOpts)
57+
}
58+
59+
private def configLogged(log: Logger): ForkOptions = {
60+
if (config.outputStrategy.isDefined) config
61+
else config.withOutputStrategy(OutputStrategy.LoggedOutput(log))
5762
}
58-
private def classpathOption(classpath: Seq[File]) =
59-
"-classpath" :: Path.makeString(classpath) :: Nil
63+
64+
private def scalaOptions(
65+
mainClass: String,
66+
classpath: Seq[File],
67+
options: Seq[String]
68+
): Seq[String] =
69+
"-classpath" :: Path.makeString(classpath) :: mainClass :: options.toList
6070
}
6171

6272
class Run(private[sbt] val newLoader: Seq[File] => ClassLoader, trapExit: Boolean)

0 commit comments

Comments
 (0)