Skip to content

Commit cd5bb09

Browse files
authored
Fix potential leaks in executePipedCommands (#12478)
1 parent b5e9178 commit cd5bb09

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

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

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

4546
import org.apache.cloudstack.utils.security.KeyStoreUtils;
47+
import org.apache.commons.collections.CollectionUtils;
4648
import org.apache.commons.io.IOUtils;
4749
import org.apache.logging.log4j.LogManager;
4850
import org.apache.logging.log4j.Logger;
@@ -708,13 +710,31 @@ public static int executeCommandForExitValue(String... command) {
708710
return executeCommandForExitValue(0, command);
709711
}
710712

713+
private static void cleanupProcesses(AtomicReference<List<Process>> processesRef) {
714+
List<Process> processes = processesRef.get();
715+
if (CollectionUtils.isNotEmpty(processes)) {
716+
for (Process process : processes) {
717+
if (process == null) {
718+
continue;
719+
}
720+
LOGGER.trace(String.format("Cleaning up process [%s] from piped commands.", process.pid()));
721+
IOUtils.closeQuietly(process.getErrorStream());
722+
IOUtils.closeQuietly(process.getOutputStream());
723+
IOUtils.closeQuietly(process.getInputStream());
724+
process.destroyForcibly();
725+
}
726+
}
727+
}
728+
711729
public static Pair<Integer, String> executePipedCommands(List<String[]> commands, long timeout) {
712730
if (timeout <= 0) {
713731
timeout = DEFAULT_TIMEOUT;
714732
}
733+
final AtomicReference<List<Process>> processesRef = new AtomicReference<>();
715734
Callable<Pair<Integer, String>> commandRunner = () -> {
716735
List<ProcessBuilder> builders = commands.stream().map(ProcessBuilder::new).collect(Collectors.toList());
717736
List<Process> processes = ProcessBuilder.startPipeline(builders);
737+
processesRef.set(processes);
718738
Process last = processes.get(processes.size()-1);
719739
try (BufferedReader reader = new BufferedReader(new InputStreamReader(last.getInputStream()))) {
720740
String line;
@@ -741,6 +761,8 @@ public static Pair<Integer, String> executePipedCommands(List<String[]> commands
741761
result.second(ERR_TIMEOUT);
742762
} catch (InterruptedException | ExecutionException e) {
743763
LOGGER.error("Error executing piped commands", e);
764+
} finally {
765+
cleanupProcesses(processesRef);
744766
}
745767
return result;
746768
}

0 commit comments

Comments
 (0)