mirror of
https://github.com/DerDavidBohl/dirigent-spring.git
synced 2026-05-02 19:40:33 -05:00
Refactor ProcessRunner to simplify command execution and improve process termination handling
This commit is contained in:
+5
-3
@@ -18,11 +18,13 @@ RUN mvn clean package -DskipTests
|
||||
# Use OpenJDK image to run the application
|
||||
FROM eclipse-temurin:25-alpine
|
||||
|
||||
# Install Docker and git
|
||||
RUN apk add docker docker-compose git
|
||||
# Install Docker, git, and tini (init system to reap zombies)
|
||||
RUN apk add docker docker-compose git tini
|
||||
|
||||
# Finish
|
||||
WORKDIR /app
|
||||
COPY --from=backend-build /app/target/*.jar app.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.profiles.active=production"]
|
||||
|
||||
# Use tini as init to reap zombie processes
|
||||
ENTRYPOINT ["/sbin/tini", "--", "java", "-jar", "app.jar", "--spring.profiles.active=production"]
|
||||
|
||||
@@ -52,24 +52,7 @@ public class ProcessRunner {
|
||||
finalEnv.putAll(env);
|
||||
}
|
||||
|
||||
// Critical: Use shell to run commands so we can kill the entire process group
|
||||
// This prevents git's child processes from becoming zombies
|
||||
String osName = System.getProperty("os.name").toLowerCase();
|
||||
boolean isWindows = osName.contains("win");
|
||||
|
||||
List<String> finalCommand;
|
||||
if (isWindows) {
|
||||
// Windows: use cmd /c
|
||||
finalCommand = new java.util.ArrayList<>();
|
||||
finalCommand.add("cmd");
|
||||
finalCommand.add("/c");
|
||||
finalCommand.addAll(commandParts);
|
||||
} else {
|
||||
// Linux/Unix: use sh -c with process group
|
||||
finalCommand = List.of("sh", "-c", String.join(" ", commandParts));
|
||||
}
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(finalCommand);
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(commandParts);
|
||||
processBuilder.directory(workingDirectory);
|
||||
processBuilder.environment().putAll(finalEnv);
|
||||
|
||||
@@ -93,7 +76,8 @@ public class ProcessRunner {
|
||||
|
||||
if (!finished) {
|
||||
log.warn("Process timed out: {}", String.join(" ", commandParts));
|
||||
killProcess(process);
|
||||
process.destroyForcibly();
|
||||
process.waitFor(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// Wait for output streams to finish reading
|
||||
@@ -105,17 +89,17 @@ public class ProcessRunner {
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Process interrupted: {}", String.join(" ", commandParts), e);
|
||||
if (process != null && process.isAlive()) {
|
||||
killProcess(process);
|
||||
process.destroyForcibly();
|
||||
try {
|
||||
process.waitFor(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
// Ensure process is terminated and streams are closed
|
||||
// Close streams to release resources
|
||||
if (process != null) {
|
||||
if (process.isAlive()) {
|
||||
log.warn("Force killing remaining process");
|
||||
killProcess(process);
|
||||
}
|
||||
// Close all streams to release resources and prevent leaks
|
||||
closeQuietly(process.getInputStream());
|
||||
closeQuietly(process.getOutputStream());
|
||||
closeQuietly(process.getErrorStream());
|
||||
@@ -136,21 +120,6 @@ public class ProcessRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Kills process and waits for it to die (reaps zombie)
|
||||
*/
|
||||
private void killProcess(Process process) {
|
||||
log.debug("Killing process: {} (alive: {})", process.pid(), process.isAlive());
|
||||
process.destroyForcibly();
|
||||
|
||||
// CRITICAL: Must waitFor() to reap the zombie
|
||||
try {
|
||||
process.waitFor(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private Thread readStream(java.io.InputStream inputStream, StringBuilder output) {
|
||||
Thread reader = new Thread(() -> {
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
||||
|
||||
Reference in New Issue
Block a user