Skip to content

Commit 96d3942

Browse files
abh1sarLocharla, Sandeep
authored andcommitted
Fix potential leaks in executePipedCommands (apache#12478)
1 parent 0f47c88 commit 96d3942

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

utils/src/main/java/com/cloud/utils/script/Script.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
import java.util.concurrent.ScheduledFuture;
4040
import java.util.concurrent.TimeUnit;
4141
import java.util.concurrent.TimeoutException;
42+
import java.util.concurrent.atomic.AtomicReference;
4243
import java.util.stream.Collectors;
4344

4445
import org.apache.cloudstack.utils.security.KeyStoreUtils;
46+
import org.apache.commons.collections.CollectionUtils;
4547
import org.apache.commons.io.IOUtils;
4648
import org.apache.logging.log4j.LogManager;
4749
import org.apache.logging.log4j.Logger;
@@ -729,13 +731,31 @@ public static int executeCommandForExitValue(String... command) {
729731
return executeCommandForExitValue(0, command);
730732
}
731733

734+
private static void cleanupProcesses(AtomicReference<List<Process>> processesRef) {
735+
List<Process> processes = processesRef.get();
736+
if (CollectionUtils.isNotEmpty(processes)) {
737+
for (Process process : processes) {
738+
if (process == null) {
739+
continue;
740+
}
741+
LOGGER.trace(String.format("Cleaning up process [%s] from piped commands.", process.pid()));
742+
IOUtils.closeQuietly(process.getErrorStream());
743+
IOUtils.closeQuietly(process.getOutputStream());
744+
IOUtils.closeQuietly(process.getInputStream());
745+
process.destroyForcibly();
746+
}
747+
}
748+
}
749+
732750
public static Pair<Integer, String> executePipedCommands(List<String[]> commands, long timeout) {
733751
if (timeout <= 0) {
734752
timeout = DEFAULT_TIMEOUT;
735753
}
754+
final AtomicReference<List<Process>> processesRef = new AtomicReference<>();
736755
Callable<Pair<Integer, String>> commandRunner = () -> {
737756
List<ProcessBuilder> builders = commands.stream().map(ProcessBuilder::new).collect(Collectors.toList());
738757
List<Process> processes = ProcessBuilder.startPipeline(builders);
758+
processesRef.set(processes);
739759
Process last = processes.get(processes.size()-1);
740760
try (BufferedReader reader = new BufferedReader(new InputStreamReader(last.getInputStream()))) {
741761
String line;
@@ -762,6 +782,8 @@ public static Pair<Integer, String> executePipedCommands(List<String[]> commands
762782
result.second(ERR_TIMEOUT);
763783
} catch (InterruptedException | ExecutionException e) {
764784
LOGGER.error("Error executing piped commands", e);
785+
} finally {
786+
cleanupProcesses(processesRef);
765787
}
766788
return result;
767789
}

0 commit comments

Comments
 (0)