Skip to content

Commit b2444c5

Browse files
#277: fixed git clone hangs
made capturing of process output and error streams parallel and asynchronously
1 parent 25c76a6 commit b2444c5

File tree

1 file changed

+36
-7
lines changed

1 file changed

+36
-7
lines changed

cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.List;
1313
import java.util.Map;
1414
import java.util.Objects;
15+
import java.util.concurrent.CompletableFuture;
1516
import java.util.stream.Collectors;
1617

1718
import com.devonfw.tools.ide.cli.CliException;
@@ -134,17 +135,21 @@ public ProcessResult run(ProcessMode processMode) {
134135

135136
this.processBuilder.command(args);
136137

137-
Process process = this.processBuilder.start();
138+
List<String> out = new ArrayList<>();
139+
List<String> err = new ArrayList<>();
138140

139-
List<String> out = null;
140-
List<String> err = null;
141+
Process process = this.processBuilder.start();
141142

142143
if (processMode == ProcessMode.DEFAULT_CAPTURE) {
143-
try (BufferedReader outReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
144-
out = outReader.lines().collect(Collectors.toList());
144+
CompletableFuture<String> outFut = readInputStream(process.getInputStream());
145+
CompletableFuture<String> errFut = readInputStream(process.getErrorStream());
146+
String outString = outFut.get();
147+
String errString = errFut.get();
148+
if (!outString.isEmpty()) {
149+
out.add(outString);
145150
}
146-
try (BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
147-
err = errReader.lines().collect(Collectors.toList());
151+
if (!errString.isEmpty()) {
152+
err.add(errString);
148153
}
149154
}
150155

@@ -171,6 +176,30 @@ public ProcessResult run(ProcessMode processMode) {
171176
}
172177
}
173178

179+
/**
180+
* Asynchronously and parallel reads {@link InputStream input stream} and stores it in {@link CompletableFuture}.
181+
* Taken from:
182+
* https://stackoverflow.com/questions/14165517/processbuilder-forwarding-stdout-and-stderr-of-started-processes-without-blocki/57483714#57483714
183+
*
184+
* @param is {@link InputStream}.
185+
* @return {@link CompletableFuture}.
186+
*/
187+
private static CompletableFuture<String> readInputStream(InputStream is) {
188+
189+
return CompletableFuture.supplyAsync(() -> {
190+
try (InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr);) {
191+
StringBuilder res = new StringBuilder();
192+
String inputLine;
193+
while ((inputLine = br.readLine()) != null) {
194+
res.append(inputLine).append(System.lineSeparator());
195+
}
196+
return res.toString();
197+
} catch (Throwable e) {
198+
throw new RuntimeException("There was a problem while executing program", e);
199+
}
200+
});
201+
}
202+
174203
private String createCommandMessage(String interpreter, String suffix) {
175204

176205
StringBuilder sb = new StringBuilder();

0 commit comments

Comments
 (0)