Registered shutdown hook to kill JVM forked by spring-boot:run

Previously, a JVM that was forked by spring-boot:run could be orphaned
when the parent process (the Maven build) was terminated in an IDE. Note
that this doesn’t happen when spring-boot:run is invoked from a shell.

This commits add a shutdown hook that registered when RunMojo forks the
JVM. The shutdown hook attempts to kill the forked JVM’s RunProcess
rather than relying on the death of the parent process being sufficient
to also kill the child.

Closes gh-5815
This commit is contained in:
Andy Wilkinson 2016-04-18 13:39:50 +01:00
parent 9a8e46952c
commit 310be23ad5

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -33,6 +33,7 @@ import org.springframework.boot.loader.tools.RunProcess;
*
* @author Phillip Webb
* @author Stephane Nicoll
* @author Andy Wilkinson
*/
@Mojo(name = "run", requiresProject = true, defaultPhase = LifecyclePhase.VALIDATE, requiresDependencyResolution = ResolutionScope.TEST)
@Execute(phase = LifecyclePhase.TEST_COMPILE)
@ -41,8 +42,10 @@ public class RunMojo extends AbstractRunMojo {
@Override
protected void runWithForkedJvm(List<String> args) throws MojoExecutionException {
try {
new RunProcess(new JavaExecutable().toString()).run(true,
args.toArray(new String[args.size()]));
RunProcess runProcess = new RunProcess(new JavaExecutable().toString());
Runtime.getRuntime()
.addShutdownHook(new Thread(new RunProcessKiller(runProcess)));
runProcess.run(true, args.toArray(new String[args.size()]));
}
catch (Exception ex) {
throw new MojoExecutionException("Could not exec java", ex);
@ -82,4 +85,19 @@ public class RunMojo extends AbstractRunMojo {
while (hasNonDaemonThreads);
}
private static class RunProcessKiller implements Runnable {
private final RunProcess runProcess;
private RunProcessKiller(RunProcess runProcess) {
this.runProcess = runProcess;
}
@Override
public void run() {
this.runProcess.kill();
}
}
}