From 82a9e82a555316e74184f1b1a23b2183f62c5887 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Wed, 28 Jul 2021 13:58:01 +0300 Subject: [PATCH] Terminate native image build container when Quarkus build terminates Fixes: #7331 --- .../NativeImageBuildContainerRunner.java | 30 +++++++++++++++++-- .../pkg/steps/NativeImageBuildRunner.java | 4 +++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java index b20e35e8b0106f..31b99f7c0c888b 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java @@ -7,9 +7,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Stream; +import org.apache.commons.lang3.RandomStringUtils; import org.jboss.logging.Logger; import io.quarkus.deployment.pkg.NativeConfig; @@ -24,6 +26,7 @@ public abstract class NativeImageBuildContainerRunner extends NativeImageBuildRu protected final NativeConfig.ContainerRuntime containerRuntime; private final String[] baseContainerRuntimeArgs; protected final String outputPath; + private final String containerName; public NativeImageBuildContainerRunner(NativeConfig nativeConfig, Path outputDir) { this.nativeConfig = nativeConfig; @@ -33,7 +36,7 @@ public NativeImageBuildContainerRunner(NativeConfig nativeConfig, Path outputDir this.baseContainerRuntimeArgs = new String[] { "--env", "LANG=C", "--rm" }; outputPath = outputDir == null ? null : outputDir.toAbsolutePath().toString(); - + containerName = "build-native-" + RandomStringUtils.random(5, true, false); } @Override @@ -67,7 +70,12 @@ protected String[] getGraalVMVersionCommand(List args) { @Override protected String[] getBuildCommand(List args) { - return buildCommand("run", getContainerRuntimeBuildArgs(), args); + List containerRuntimeBuildArgs = getContainerRuntimeBuildArgs(); + List effectiveContainerRuntimeBuildArgs = new ArrayList<>(containerRuntimeBuildArgs.size() + 2); + effectiveContainerRuntimeBuildArgs.addAll(containerRuntimeBuildArgs); + effectiveContainerRuntimeBuildArgs.add("--name"); + effectiveContainerRuntimeBuildArgs.add(containerName); + return buildCommand("run", effectiveContainerRuntimeBuildArgs, args); } @Override @@ -81,6 +89,24 @@ protected void objcopy(String... args) { runCommand(command, null, null); } + @Override + public void addShutdownHook(Process process) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + if (process.isAlive()) { + try { + Process removeProcess = new ProcessBuilder( + List.of(containerRuntime.getExecutableName(), "rm", "-f", containerName)) + .redirectOutput(ProcessBuilder.Redirect.DISCARD) + .redirectError(ProcessBuilder.Redirect.DISCARD) + .start(); + removeProcess.waitFor(2_000, TimeUnit.SECONDS); + } catch (IOException | InterruptedException e) { + log.debug("Unable to stop running container", e); + } + } + })); + } + protected List getContainerRuntimeBuildArgs() { List containerRuntimeArgs = new ArrayList<>(); nativeConfig.containerRuntimeOptions.ifPresent(containerRuntimeArgs::addAll); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java index 6c064308034893..dfd679c6338f95 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildRunner.java @@ -42,6 +42,9 @@ public GraalVM.Version getGraalVMVersion() { public void setup(boolean processInheritIODisabled) { } + public void addShutdownHook(Process buildNativeProcess) { + } + public int build(List args, String nativeImageName, String resultingExecutableName, Path outputDir, boolean debugEnabled, boolean processInheritIODisabled) throws InterruptedException, IOException { @@ -53,6 +56,7 @@ public int build(List args, String nativeImageName, String resultingExec .directory(outputDir.toFile()); log.info(String.join(" ", buildCommand).replace("$", "\\$")); final Process process = ProcessUtil.launchProcessStreamStdOut(processBuilder, processInheritIODisabled); + addShutdownHook(process); ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(new ErrorReplacingProcessReader(process.getErrorStream(), outputDir.resolve("reports").toFile(), errorReportLatch));