From 781e2fc703d2eb59197cf5239a152595a8bb8d20 Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Wed, 21 Jan 2026 09:01:02 +0530 Subject: [PATCH 1/2] Fix potential leaks in executePipedCommands --- .../java/com/cloud/utils/script/Script.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 6c62c9106484..ef6cec2032a4 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -40,9 +40,11 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import org.apache.cloudstack.utils.security.KeyStoreUtils; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -712,9 +714,11 @@ public static Pair executePipedCommands(List commands if (timeout <= 0) { timeout = DEFAULT_TIMEOUT; } + final AtomicReference> processesRef = new AtomicReference<>(); Callable> commandRunner = () -> { List builders = commands.stream().map(ProcessBuilder::new).collect(Collectors.toList()); List processes = ProcessBuilder.startPipeline(builders); + processesRef.set(processes); Process last = processes.get(processes.size()-1); try (BufferedReader reader = new BufferedReader(new InputStreamReader(last.getInputStream()))) { String line; @@ -741,6 +745,20 @@ public static Pair executePipedCommands(List commands result.second(ERR_TIMEOUT); } catch (InterruptedException | ExecutionException e) { LOGGER.error("Error executing piped commands", e); + } finally { + List processes = processesRef.get(); + if (CollectionUtils.isNotEmpty(processes)) { + for (Process process : processes) { + if (process == null) { + continue; + } + LOGGER.trace(String.format("Cleaning up process [%s] from piped commands.", process.pid())); + IOUtils.closeQuietly(process.getErrorStream()); + IOUtils.closeQuietly(process.getOutputStream()); + IOUtils.closeQuietly(process.getInputStream()); + process.destroyForcibly(); + } + } } return result; } From 9554401006511a3ceb19ca4aa7923e0541908e3b Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:37:34 +0530 Subject: [PATCH 2/2] refactor --- .../java/com/cloud/utils/script/Script.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index ef6cec2032a4..ffda782edda2 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -710,6 +710,22 @@ public static int executeCommandForExitValue(String... command) { return executeCommandForExitValue(0, command); } + private static void cleanupProcesses(AtomicReference> processesRef) { + List processes = processesRef.get(); + if (CollectionUtils.isNotEmpty(processes)) { + for (Process process : processes) { + if (process == null) { + continue; + } + LOGGER.trace(String.format("Cleaning up process [%s] from piped commands.", process.pid())); + IOUtils.closeQuietly(process.getErrorStream()); + IOUtils.closeQuietly(process.getOutputStream()); + IOUtils.closeQuietly(process.getInputStream()); + process.destroyForcibly(); + } + } + } + public static Pair executePipedCommands(List commands, long timeout) { if (timeout <= 0) { timeout = DEFAULT_TIMEOUT; @@ -746,19 +762,7 @@ public static Pair executePipedCommands(List commands } catch (InterruptedException | ExecutionException e) { LOGGER.error("Error executing piped commands", e); } finally { - List processes = processesRef.get(); - if (CollectionUtils.isNotEmpty(processes)) { - for (Process process : processes) { - if (process == null) { - continue; - } - LOGGER.trace(String.format("Cleaning up process [%s] from piped commands.", process.pid())); - IOUtils.closeQuietly(process.getErrorStream()); - IOUtils.closeQuietly(process.getOutputStream()); - IOUtils.closeQuietly(process.getInputStream()); - process.destroyForcibly(); - } - } + cleanupProcesses(processesRef); } return result; }