Skip to content
Permalink
Browse files

Adding additional shutdown hook in case a service in the background c…

…anẗ be terminated correctly.
  • Loading branch information...
atooni committed Apr 18, 2019
1 parent 8756ac0 commit 82b2acfdb4e50bb65af9f56532eb4692fa5c5fe1
@@ -11,6 +11,7 @@ import blended.updater.config.OverlayConfigCompanion
import blended.util.logging.Logger

import scala.annotation.tailrec
import scala.concurrent.duration._

object JvmLauncher {

@@ -105,6 +106,7 @@ class JvmLauncher() {
arguments = config.otherArgs.toArray ++ Array("--write-system-properties", sysPropsFile.getAbsolutePath()),
interactive = false,
errorsIntoOutput = false,
shutdownTimeout = config.shutdownTimeout,
directory = new File(".").getAbsoluteFile()
)
val retVal = p.waitFor
@@ -137,6 +139,7 @@ class JvmLauncher() {
arguments = config.otherArgs.toArray,
interactive = config.interactive,
errorsIntoOutput = false,
shutdownTimeout = config.shutdownTimeout,
directory = new File(".").getAbsoluteFile()
)
log.debug("Process started: " + p)
@@ -168,12 +171,14 @@ class JvmLauncher() {
}

case class JvmLauncherConfig(
classpath: Seq[File] = Seq(),
otherArgs: Seq[String] = Seq(),
action: Option[String] = None,
jvmOpts: Seq[String] = Seq(),
interactive: Boolean = true,
restartDelaySec: Option[Int] = None) {
classpath: Seq[File] = Seq(),
otherArgs: Seq[String] = Seq(),
action: Option[String] = None,
jvmOpts: Seq[String] = Seq(),
interactive: Boolean = true,
shutdownTimeout : FiniteDuration = 5.seconds,
restartDelaySec: Option[Int] = None
) {

private[this] lazy val prettyPrint : String =
s"""${getClass().getSimpleName()}(
@@ -212,6 +217,9 @@ class JvmLauncher() {
case Seq(interactive, rest @_*) if interactive.startsWith("-interactive") =>
val iAct = interactive.substring("-interactive=".length).toBoolean
parse(rest, initialConfig.copy(interactive = iAct))
case Seq(maxShutdown, rest @ _*) if maxShutdown.startsWith("-maxShutdown") =>
val seconds : Int = Integer.parseInt(maxShutdown.substring("-maxShutdown=".length()))
parse(rest, initialConfig.copy(shutdownTimeout = seconds.seconds))
case _ =>
sys.error("Cannot parse arguments: " + args)
}
@@ -233,7 +241,8 @@ class JvmLauncher() {
arguments: Array[String],
interactive: Boolean = false,
errorsIntoOutput: Boolean = true,
directory: File = new File(".")
directory: File = new File("."),
shutdownTimeout : FiniteDuration
): RunningProcess = {

log.debug("About to run Java process")
@@ -264,7 +273,7 @@ class JvmLauncher() {
// if (!env.isEmpty) env.foreach { case (k, v) => pb.environment().put(k, v) }
val p = pb.start

new RunningProcess(p, errorsIntoOutput, interactive)
new RunningProcess(p, errorsIntoOutput, interactive, shutdownTimeout)
}

/**
@@ -2,14 +2,26 @@ package blended.launcher.jvmrunner

import java.io.{IOException, InputStream, OutputStream}

import blended.util.logging.Logger

import scala.concurrent.duration._

private[jvmrunner]
class RunningProcess(process: Process, errorsIntoOutput: Boolean, interactive: Boolean) {
class RunningProcess(
process: Process,
errorsIntoOutput: Boolean,
interactive: Boolean,
shutdownTimeout : FiniteDuration
) {

private[this] val errThread = asyncCopy(process.getErrorStream, if (errorsIntoOutput) Console.out else Console.err)
private[this] val inThread = asyncCopy(process.getInputStream, Console.out, interactive)
private[this] val errThread : Thread = asyncCopy(process.getErrorStream, if (errorsIntoOutput) Console.out else Console.err)
private[this] val inThread : Thread = asyncCopy(process.getInputStream, Console.out, interactive)

private[this] val in = System.in
private[this] val out = process.getOutputStream
private[this] val in : InputStream = System.in
private[this] val out : OutputStream = process.getOutputStream

private[this] val log : Logger = Logger[RunningProcess]
private[this] val sleepInterval : FiniteDuration = 50.millis

private[this] val outThread = new Thread("StreamCopyThread") {
setDaemon(true)
@@ -25,7 +37,7 @@ class RunningProcess(process: Process, errorsIntoOutput: Boolean, interactive: B
out.flush()
}
} else {
Thread.sleep(50)
Thread.sleep(sleepInterval.toMillis)
}
}
} catch {
@@ -35,7 +47,12 @@ class RunningProcess(process: Process, errorsIntoOutput: Boolean, interactive: B
}
}

if (interactive) outThread.start()
if (interactive) {
log.info("Starting console read thread ...")
outThread.start()
} else {
log.info("Container is started without console read thread ...")
}

def waitFor(): Int = {
try {
@@ -48,13 +65,33 @@ class RunningProcess(process: Process, errorsIntoOutput: Boolean, interactive: B
}
}

private def waitUntilStopped(t : FiniteDuration) : Boolean = {

val now : Long = System.currentTimeMillis()
val end : Long = now + t.toMillis

while(process.isAlive() && System.currentTimeMillis() <= end) {
Thread.sleep(sleepInterval.toMillis)
}

process.isAlive()
}

def stop(): Int = {

log.info("Stopping container JVM ...")
if (interactive) {
outThread.interrupt()
} else {
out.write("stop 0\n".getBytes())
}

// If the process is still alive after we tried to stop it we will kill it
if (waitUntilStopped(shutdownTimeout)) {
log.info("Killing container JVM after maximum shutdown timeout ...")
process.destroy()
}

out.flush()
out.close()
waitFor()
@@ -36,7 +36,7 @@ fi

# Whether to start the container in interactive mode
if [ -z "${INTERACTIVE}" ]; then
INTERACTIVE=true
INTERACTIVE=false
fi

if [ "${INTERACTIVE}" == "true" ]; then
@@ -47,7 +47,7 @@ set CLASS=blended.launcher.jvmrunner.JvmLauncher
--StartMode=jvm ^
--StopMode=jvm ^
--StartClass=%CLASS% ^
--StartParams="start;-interactive=false;%CONTAINER_JAVA_OPTS%;-cp='%CP%';-restartDelay=%RESTART_DELAY%;--;blended.launcher.Launcher;--profile-lookup;%BLENDED_HOME%/launch.conf;--init-container-id;--framework-restart;false" ^
--StartParams="start;-interactive=false;-maxShutdown=10;%CONTAINER_JAVA_OPTS%;-cp='%CP%';-restartDelay=%RESTART_DELAY%;--;blended.launcher.Launcher;--profile-lookup;%BLENDED_HOME%/launch.conf;--init-container-id;--framework-restart;false" ^
--JvmOptions="%LOGBACK_CONFIG_SETTING%;-Dblended.home=%BLENDED_HOME%;-Xmx24m" ^
--StopClass=%CLASS% ^
--StopParams="stop" ^

0 comments on commit 82b2acf

Please sign in to comment.
You can’t perform that action at this time.