From a7e13810860e37fcc2c4a5de1a1778fed83bd7f1 Mon Sep 17 00:00:00 2001 From: Katelyn Baker Date: Fri, 13 Jul 2018 18:15:05 +0100 Subject: [PATCH] CORDA-1634 - Destroy child processes when parent exits. (#3368) (#3604) * [CORDA-1634] Destroy child processes when parent exits. * Add comment. * Register Shutdownhook for processes regardless of whether the Driver was initialized with * Add comment. * Revert "Add comment." This reverts commit a5e78c379fba4e132cb3287997e77e21a6600947. * Add comment. * Add shutdown hook in ShutdownManager.registerProcessShutdown. * Initialize the ShutdownManager with a shutdown hook to ensure that is called. * Add comment. --- .../net/corda/testing/node/internal/DriverDSLImpl.kt | 9 +++++++-- .../net/corda/testing/node/internal/ShutdownManager.kt | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt index 5f3ea4b17a..e255cdd499 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt @@ -95,6 +95,7 @@ class DriverDSLImpl( val compatibilityZone: CompatibilityZoneParams?, val networkParameters: NetworkParameters ) : InternalDriverDSL { + private var _executorService: ScheduledExecutorService? = null val executorService get() = _executorService!! private var _shutdownManager: ShutdownManager? = null @@ -699,6 +700,12 @@ class DriverDSLImpl( val debugPort = if (isDebug) debugPortAllocation.nextPort() else null val monitorPort = if (jmxPolicy.startJmxHttpServer) jmxPolicy.jmxHttpServerPortAllocation?.nextPort() else null val process = startOutOfProcessNode(config, quasarJarPath, debugPort, jolokiaJarPath, monitorPort, systemProperties, cordappPackages, maximumHeapSize) + + // Destroy the child process when the parent exits.This is needed even when `waitForAllNodesToFinish` is + // true because we don't want orphaned processes in the case that the parent process is terminated by the + // user, for example when the `tools:explorer:runDemoNodes` gradle task is stopped with CTRL-C. + shutdownManager.registerProcessShutdown(process) + if (waitForAllNodesToFinish) { state.locked { processes += object : Waitable { @@ -707,8 +714,6 @@ class DriverDSLImpl( } } } - } else { - shutdownManager.registerProcessShutdown(process) } val p2pReadyFuture = addressMustBeBoundFuture(executorService, config.corda.p2pAddress, process) return p2pReadyFuture.flatMap { diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ShutdownManager.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ShutdownManager.kt index 433cff4c00..f69c4e8de1 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ShutdownManager.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ShutdownManager.kt @@ -7,12 +7,18 @@ import net.corda.core.utilities.Try import net.corda.core.utilities.contextLogger import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.seconds +import net.corda.nodeapi.internal.addShutdownHook import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.TimeoutException import java.util.concurrent.atomic.AtomicInteger class ShutdownManager(private val executorService: ExecutorService) { + + init { + addShutdownHook { shutdown() } + } + private class State { val registeredShutdowns = ArrayList Unit>>() var isShuttingDown = false