Merge pull request #5793 from eatkins/kill-processes

Kill external processes on sigint
This commit is contained in:
eugene yokota 2020-08-26 11:07:52 -04:00 committed by GitHub
commit 788fd4aa28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 2 deletions

View File

@ -0,0 +1,33 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util
import java.util.concurrent.ConcurrentHashMap
import scala.sys.process.Process
/**
* Manages forked processes created by sbt. Any process registered
* with RunningProcesses can be killed with the killAll method. In
* particular, this can be used in a signal handler to kill these
* processes when the user inputs ctrl+c.
*/
private[sbt] object RunningProcesses {
val active = ConcurrentHashMap.newKeySet[Process]
def add(process: Process): Unit = active.synchronized {
active.add(process)
()
}
def remove(process: Process): Unit = active.synchronized {
active.remove(process)
()
}
def killAll(): Unit = active.synchronized {
active.forEach(_.destroy())
active.clear()
}
}

View File

@ -17,8 +17,8 @@ import sbt.io.IO
import sbt.util.Logger
import sbt.ConcurrentRestrictions.Tag
import sbt.protocol.testing._
import sbt.internal.util.ConsoleAppender
import sbt.internal.util.Util.{ AnyOps, none }
import sbt.internal.util.{ ConsoleAppender, RunningProcesses }
private[sbt] object ForkTests {
def apply(
@ -147,7 +147,13 @@ private[sbt] object ForkTests {
classOf[ForkMain].getCanonicalName,
server.getLocalPort.toString
)
val ec = Fork.java(fork, options)
val p = Fork.java.fork(fork, options)
RunningProcesses.add(p)
val ec = try p.exitValue()
finally {
if (p.isAlive) p.destroy()
RunningProcesses.remove(p)
}
val result =
if (ec != 0)
TestOutput(

View File

@ -480,6 +480,7 @@ object EvaluateTask {
def cancelAndShutdown(): Unit = {
println("")
log.warn("Canceling execution...")
RunningProcesses.killAll()
ConcurrentRestrictions.cancelAll()
shutdown()
}

View File

@ -14,12 +14,14 @@ import java.net.SocketException
import scala.sys.process.Process
import sbt.internal.scripted.{ StatementHandler, TestFailed }
import sbt.internal.util.RunningProcesses
import xsbt.IPC
final case class SbtInstance(process: Process, server: IPC.Server)
final class SbtHandler(remoteSbtCreator: RemoteSbtCreator) extends StatementHandler {
Signals.register(() => RunningProcesses.killAll())
type State = Option[SbtInstance]
@ -63,6 +65,9 @@ final class SbtHandler(remoteSbtCreator: RemoteSbtCreator) extends StatementHand
()
} catch {
case _: IOException => process.destroy()
} finally {
if (process.isAlive) process.destroy()
RunningProcesses.remove(process)
}
}
@ -76,6 +81,7 @@ final class SbtHandler(remoteSbtCreator: RemoteSbtCreator) extends StatementHand
def newRemote(server: IPC.Server): Process = {
val p = remoteSbtCreator.newRemote(server)
RunningProcesses.add(p)
try receive("Remote sbt initialization failed", server)
catch { case _: SocketException => throw new TestFailed("Remote sbt initialization failed") }
p