This is an automated email from the ASF dual-hosted git repository. sseifert pushed a commit to branch feature/SLING-13037-shutdown-hook-windows in repository https://gitbox.apache.org/repos/asf/sling-feature-launcher-maven-plugin.git
commit adecffe1aff4aad2fe7ee87fca9618cb8c46e58f Author: Stefan Seifert <[email protected]> AuthorDate: Fri Dec 19 12:53:57 2025 +0100 SLING-13037 Refactor process shutdown code to always distinguish between windows and non-windows environments --- .../maven/feature/launcher/ProcessTracker.java | 55 +++++++++++++++++----- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/ProcessTracker.java b/src/main/java/org/apache/sling/maven/feature/launcher/ProcessTracker.java index 63fda7d..efa54e1 100644 --- a/src/main/java/org/apache/sling/maven/feature/launcher/ProcessTracker.java +++ b/src/main/java/org/apache/sling/maven/feature/launcher/ProcessTracker.java @@ -23,7 +23,10 @@ import javax.inject.Singleton; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; import org.apache.maven.shared.utils.Os; import org.slf4j.Logger; @@ -36,6 +39,30 @@ public class ProcessTracker { private static final Logger LOG = LoggerFactory.getLogger(ProcessTracker.class); static void stop(Process process) throws InterruptedException { + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + stopWithDescendants(process, false); + } else { + stopDirectly(process, false); + } + } + + static void stopForcibly(Process process) throws InterruptedException { + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + stopWithDescendants(process, true); + } else { + stopDirectly(process, true); + } + } + + /** + * Use this for non-windows OS only by stopping the process directly, not caring about descendants. + */ + private static void stopDirectly(Process process, boolean forcibly) throws InterruptedException { + if (forcibly) { + LOG.debug("Forcibly destroy process: {}", process); + process.destroyForcibly(); + return; + } LOG.debug("Destroy process: {}", process); process.destroy(); boolean stopped = process.waitFor(30, TimeUnit.SECONDS); @@ -51,7 +78,7 @@ public class ProcessTracker { * The Launcher is started from a .bat file, and killing the known process only kills the .bat process, not the spawned java process. * So we try to kill all descendant processes first. */ - static void stopWithDescendants(Process process) throws InterruptedException { + private static void stopWithDescendants(Process process, boolean forcibly) throws InterruptedException { LOG.debug("Destroy process with descendants: {}", process); ProcessHandle processHandle = ProcessHandle.of(process.pid()).orElse(null); @@ -60,7 +87,12 @@ public class ProcessTracker { return; } - processHandle.descendants().forEach(childProcess -> { + for (ProcessHandle childProcess : processHandle.descendants().collect(Collectors.toList())) { + if (forcibly) { + LOG.debug("Forcibly destroy child process: {}", childProcess); + childProcess.destroyForcibly(); + return; + } LOG.debug("Destroy child process: {}", childProcess); childProcess.destroy(); try { @@ -70,12 +102,12 @@ public class ProcessTracker { childProcess.destroyForcibly(); } LOG.debug("Destroy child process finished: {}", childProcess); - } catch (Exception ex) { + } catch (TimeoutException | ExecutionException ex) { LOG.error("Error while stopping child process {}: {}", childProcess, ex.getMessage(), ex); } - }); + } - stop(process); + stopDirectly(process, forcibly); } private final Object sync = new Object(); @@ -98,7 +130,11 @@ public class ProcessTracker { LOG.error( "Launch {} was not shut down! Destroying forcibly from shutdown hook.", entry.getKey()); - process.destroyForcibly(); + try { + ProcessTracker.stopForcibly(process); + } catch (InterruptedException e) { + interrupt(); + } } } }); @@ -116,11 +152,6 @@ public class ProcessTracker { LOG.warn("Process not found in process list, skip stopping: {}", id); return; } - - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - stopWithDescendants(process); - } else { - stop(process); - } + ProcessTracker.stop(process); } }
