Commit 9b198da9 authored by Romain Reuillon's avatar Romain Reuillon

Process should be killed when thread is killed

parent f4c9f512
......@@ -9,8 +9,8 @@ libraryDependencies += "org.typelevel" %% "squants" % "1.6.0"
//libraryDependencies += "org.typelevel" %% "cats-core" % "1.4.0"
libraryDependencies += "com.github.pathikrit" %% "better-files" % "3.8.0"
libraryDependencies += "org.apache.commons" % "commons-compress" % "1.19"
libraryDependencies += "org.apache.commons" % "commons-exec" % "1.3"
val circeVersion = "0.12.3"
......
package container
import java.io.File
import java.io.{File, PrintStream}
import java.util.UUID
import container.ImageBuilder.checkImageFile
......@@ -61,7 +61,7 @@ object Docker {
bind: Seq[(String, String)] = Vector.empty,
workDirectory: Option[String] = None,
environmentVariables: Seq[(String, String)] = Vector.empty,
logger: ProcessLogger = tool.outputLogger) = {
logger: PrintStream = tool.outputLogger) = {
import better.files._
val id = UUID.randomUUID().toString
......@@ -81,7 +81,11 @@ object Docker {
|COPY ./$runFile /
|""".stripMargin)
Seq(dockerCommand, "build", "-t", id, buildDirectory.toJava.getAbsolutePath) !! logger
ProcessUtil.execute(
Seq(dockerCommand, "build", "-t", id, buildDirectory.toJava.getAbsolutePath),
logger,
logger
)
def variables =
image.env.getOrElse(Seq.empty).flatMap { e =>
......@@ -110,16 +114,14 @@ object Docker {
id,
) ++ workDirectoryValue ++ volumes ++ variables ++ Seq(id, "/bin/sh", s"/$runFile")
try {
val process = Runtime.getRuntime.synchronized { run run logger }
process.exitValue()
} finally Seq("docker", "rmi", id) !!
try ProcessUtil.execute(run, logger, logger)
finally ProcessUtil.execute(Seq("docker", "rmi", id), logger, logger)
} finally buildDirectory.delete()
}
def clean(image: BuiltDockerImage, dockerCommand: String = "docker") = {
(s"$dockerCommand rmi ${image.imageId}").!!
image.file.delete()
}
// def clean(image: BuiltDockerImage, dockerCommand: String = "docker") = {
// (s"$dockerCommand rmi ${image.imageId}").!!
// image.file.delete()
// }
}
package container
import java.io.PrintStream
import org.apache.commons.exec.PumpStreamHandler
import org.apache.commons.exec.ShutdownHookProcessDestroyer
object ProcessUtil {
val processDestroyer = new ShutdownHookProcessDestroyer
def execute(cmd: Seq[String], out: PrintStream = System.out, err: PrintStream = System.err, env: Seq[String] = Seq.empty) = {
val runtime = Runtime.getRuntime
val process = runtime.synchronized {
runtime.exec(
cmd.toArray,
env.toArray)
}
executeProcess(process, out = out, err = err)
}
def executeProcess(process: Process, out: PrintStream = System.out, err: PrintStream = System.err) = {
val pump = new PumpStreamHandler(out, err)
pump.setProcessOutputStream(process.getInputStream)
pump.setProcessErrorStream(process.getErrorStream)
processDestroyer.add(process)
try {
pump.start
try process.waitFor
catch {
case e: Throwable
process.destroyForcibly()
throw e
} finally {
pump.stop
}
} finally processDestroyer.remove(process)
process.exitValue
}
}
......@@ -17,7 +17,7 @@ package container
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.{ BufferedOutputStream, BufferedWriter, File, FileOutputStream, OutputStreamWriter, PrintWriter }
import java.io.{ BufferedOutputStream, BufferedWriter, File, FileOutputStream, OutputStreamWriter, PrintStream, PrintWriter }
import java.nio.file.attribute.PosixFileAttributes
import container.ImageBuilder.checkImageFile
......@@ -306,9 +306,9 @@ object Proot {
bind: Seq[(String, String)] = Vector.empty,
workDirectory: Option[String] = None,
environmentVariables: Seq[(String, String)] = Vector.empty,
logger: ProcessLogger = tool.outputLogger,
logger: PrintStream = tool.outputLogger,
noSeccomp: Boolean = false,
kernel: Option[String] = None) = {
kernel: Option[String] = None): Int = {
checkImageFile(image.file)
......@@ -332,10 +332,8 @@ object Proot {
noSeccomp = noSeccomp,
kernel = kernel)
try {
val process = Runtime.getRuntime.synchronized { script.getCanonicalPath run logger }
process.exitValue()
} finally script.delete()
try ProcessUtil.execute(Seq(script.getCanonicalPath), logger, logger)
finally script.delete()
}
}
......@@ -19,7 +19,7 @@ package container
import container.ImageBuilder.checkImageFile
import container.OCI.ConfigurationData
import java.io.File
import java.io.{ File, PrintStream }
import java.util.UUID
import scala.sys.process._
......@@ -61,7 +61,7 @@ object Singularity {
Seq(singularityCommand, "run", file) ++ command.getOrElse(image.command) !!
}
def buildSIF(image: FlatImage, sif: File, tmpDirectory: File, singularityCommand: String = "singularity", logger: ProcessLogger = tool.outputLogger) = {
def buildSIF(image: FlatImage, sif: File, tmpDirectory: File, singularityCommand: String = "singularity", logger: PrintStream = tool.outputLogger) = {
import better.files._
val id = UUID.randomUUID().toString
......@@ -84,7 +84,11 @@ object Singularity {
|""".stripMargin)
val sandbox = (buildDirectory / "empty")
Seq(singularityCommand, "build", "--fakeroot", sandbox.toJava.getAbsolutePath, (buildDirectory / "empty.def").toJava.getAbsolutePath) !! logger
ProcessUtil.execute(
Seq(singularityCommand, "build", "--fakeroot", sandbox.toJava.getAbsolutePath, (buildDirectory / "empty.def").toJava.getAbsolutePath),
logger,
logger)
} finally buildDirectory.delete()
}
......@@ -97,7 +101,7 @@ object Singularity {
bind: Seq[(String, String)] = Vector.empty,
workDirectory: Option[String] = None,
environmentVariables: Seq[(String, String)] = Vector.empty,
logger: ProcessLogger = tool.outputLogger) = {
logger: PrintStream = tool.outputLogger) = {
import better.files._
val id = UUID.randomUUID().toString
......@@ -127,24 +131,22 @@ object Singularity {
val absoluteRootFS = (image.file.toScala / FlatImage.rootfsName).toJava.getAbsolutePath
(Seq(runFile) ++ bind.unzip._2) foreach { f => new java.io.File((image.file.toScala / FlatImage.rootfsName).toJava, f).toScala.touch() }
val process =
Runtime.getRuntime.synchronized {
Process(
Seq(
singularityCommand,
"--silent",
"exec",
"-w") ++
pwd ++
Seq(
"--home", s"$absoluteRootFS/root:/root",
"-B", s"$absoluteRootFS/tmp:/tmp",
"-B", s"$absoluteRootFS/var/tmp:/var/tmp") ++ bind.flatMap { case (f, t) => Seq("-B", s"$f:$t") } ++
Seq("-B", s"${(buildDirectory / runFile).toJava.getAbsolutePath}:/$runFile") ++
Seq(absoluteRootFS, "sh", s"/$runFile"), None, extraEnv = variables: _*) run logger
}
process.exitValue()
ProcessUtil.execute(
Seq(
singularityCommand,
"--silent",
"exec",
"-w") ++
pwd ++
Seq(
"--home", s"$absoluteRootFS/root:/root",
"-B", s"$absoluteRootFS/tmp:/tmp",
"-B", s"$absoluteRootFS/var/tmp:/var/tmp") ++ bind.flatMap { case (f, t) => Seq("-B", s"$f:$t") } ++
Seq("-B", s"${(buildDirectory / runFile).toJava.getAbsolutePath}:/$runFile") ++
Seq(absoluteRootFS, "sh", s"/$runFile"),
logger,
logger,
variables.map { case (n, v) => s"$n=$v" })
// TODO copy new directories at the root in the sandbox back to rootfs ?
} finally buildDirectory.delete()
......
package container
import java.io.{ OutputStream, PrintStream }
import scala.sys.process.ProcessLogger
/*
......@@ -19,6 +21,9 @@ import scala.sys.process.ProcessLogger
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package object tool {
def outputLogger = ProcessLogger(s => println(s), s => println(s))
def nullLogger = ProcessLogger(s => (), s => ())
def outputLogger = System.out
def nullLogger = new PrintStream(new OutputStream {
override def write(i: Int): Unit = {}
})
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment