This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push:
new cd5bb09d0d1 Fix potential leaks in executePipedCommands (#12478)
cd5bb09d0d1 is described below
commit cd5bb09d0d19e4e01baeaad7a6cbe14ab2db28bc
Author: Abhisar Sinha <[email protected]>
AuthorDate: Thu Jan 22 15:29:41 2026 +0530
Fix potential leaks in executePipedCommands (#12478)
---
.../main/java/com/cloud/utils/script/Script.java | 22 ++++++++++++++++++++++
1 file changed, 22 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 6c62c910648..ffda782edda 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.ScheduledExecutorService;
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;
@@ -708,13 +710,31 @@ public class Script implements Callable<String> {
return executeCommandForExitValue(0, command);
}
+ private static void cleanupProcesses(AtomicReference<List<Process>>
processesRef) {
+ List<Process> 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<Integer, String> executePipedCommands(List<String[]>
commands, long timeout) {
if (timeout <= 0) {
timeout = DEFAULT_TIMEOUT;
}
+ final AtomicReference<List<Process>> processesRef = new
AtomicReference<>();
Callable<Pair<Integer, String>> commandRunner = () -> {
List<ProcessBuilder> builders =
commands.stream().map(ProcessBuilder::new).collect(Collectors.toList());
List<Process> 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 +761,8 @@ public class Script implements Callable<String> {
result.second(ERR_TIMEOUT);
} catch (InterruptedException | ExecutionException e) {
LOGGER.error("Error executing piped commands", e);
+ } finally {
+ cleanupProcesses(processesRef);
}
return result;
}