aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api/src
diff options
context:
space:
mode:
authorEvgeny Mandrikov <mandrikov@gmail.com>2011-10-10 21:03:06 +0400
committerEvgeny Mandrikov <mandrikov@gmail.com>2011-10-10 21:38:33 +0400
commit4fe55966cfa022ae8b9dc3f0ca7ead7d74bc7251 (patch)
tree7653a5d7f371fa0d0d3a2ab44b82667f93e1b958 /sonar-plugin-api/src
parent3d8b9059a51658ea06ab7c4705a1a26dd005a154 (diff)
downloadsonarqube-4fe55966cfa022ae8b9dc3f0ca7ead7d74bc7251.tar.gz
sonarqube-4fe55966cfa022ae8b9dc3f0ca7ead7d74bc7251.zip
SONAR-2852 CommandExecutor must explicitly close all streams
Diffstat (limited to 'sonar-plugin-api/src')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/command/CommandExecutor.java45
1 files changed, 37 insertions, 8 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/command/CommandExecutor.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/command/CommandExecutor.java
index 4b8e4c93e4c..1980f870c3d 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/command/CommandExecutor.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/command/CommandExecutor.java
@@ -19,16 +19,16 @@
*/
package org.sonar.api.utils.command;
-import org.apache.commons.io.IOUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.*;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Synchronously execute a native command line. It's much more limited than the Apache Commons Exec library.
* For example it does not allow to get process output, to run asynchronously or to automatically quote
@@ -51,6 +51,8 @@ public final class CommandExecutor {
public int execute(Command command, long timeoutMilliseconds) {
ExecutorService executorService = null;
Process process = null;
+ StreamGobbler outputGobbler = null;
+ StreamGobbler errorGobbler = null;
try {
LoggerFactory.getLogger(getClass()).debug("Executing command: " + command);
ProcessBuilder builder = new ProcessBuilder(command.toStrings());
@@ -60,16 +62,15 @@ public final class CommandExecutor {
process = builder.start();
// consume and display the error and output streams
- StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream());
- StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream());
+ outputGobbler = new StreamGobbler(process.getInputStream());
+ errorGobbler = new StreamGobbler(process.getErrorStream());
outputGobbler.start();
errorGobbler.start();
final Process finalProcess = process;
Callable<Integer> call = new Callable<Integer>() {
public Integer call() throws Exception {
- finalProcess.waitFor();
- return finalProcess.exitValue();
+ return finalProcess.waitFor();
}
};
@@ -85,19 +86,47 @@ public final class CommandExecutor {
throw new CommandException(command, e);
} finally {
+ if (outputGobbler != null) {
+ waitUntilFinish(outputGobbler);
+ }
+
+ if (errorGobbler != null) {
+ waitUntilFinish(errorGobbler);
+ }
+
+ if (process != null) {
+ closeStreams(process);
+ }
+
if (executorService != null) {
executorService.shutdown();
}
}
}
+ private void closeStreams(Process process) {
+ IOUtils.closeQuietly(process.getInputStream());
+ IOUtils.closeQuietly(process.getOutputStream());
+ IOUtils.closeQuietly(process.getErrorStream());
+ }
+
+ private void waitUntilFinish(StreamGobbler thread) {
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+
private static class StreamGobbler extends Thread {
InputStream is;
StreamGobbler(InputStream is) {
+ super("ProcessStreamGobbler");
this.is = is;
}
+ @Override
public void run() {
Logger logger = LoggerFactory.getLogger(CommandExecutor.class);
InputStreamReader isr = new InputStreamReader(is);