Skip to content

Commit a99d96d

Browse files
authored
Improve process error handling (#532)
1 parent e72b51f commit a99d96d

2 files changed

Lines changed: 28 additions & 13 deletions

File tree

src/main/java/com/github/stickerifier/stickerify/media/MediaHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static MultimediaInfo retrieveMultimediaInfo(File file) throws MediaException, I
186186
var command = new String[] {
187187
"ffprobe",
188188
"-hide_banner",
189-
"-v", "quiet",
189+
"-v", "error",
190190
"-print_format", "json",
191191
"-show_format",
192192
"-show_streams",

src/main/java/com/github/stickerifier/stickerify/process/ProcessHelper.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.slf4j.event.Level;
88

99
import java.io.IOException;
10+
import java.io.UncheckedIOException;
1011
import java.util.StringJoiner;
1112
import java.util.concurrent.Semaphore;
1213
import java.util.concurrent.TimeUnit;
@@ -22,7 +23,7 @@ public final class ProcessHelper {
2223
* environment variable (defaults to 4).
2324
*
2425
* @param command the command to be executed
25-
* @return the merged stdout/stderr of the command
26+
* @return the standard output of the command
2627
* @throws ProcessException either if:
2728
* <ul>
2829
* <li>the command was unsuccessful
@@ -35,30 +36,44 @@ public final class ProcessHelper {
3536
public static String executeCommand(final String... command) throws ProcessException, InterruptedException {
3637
SEMAPHORE.acquire();
3738

38-
try (var process = new ProcessBuilder(command).redirectErrorStream(true).start()) {
39-
var output = new StringJoiner("\n");
40-
var readerThread = Thread.ofVirtual().start(() -> {
39+
try (var process = new ProcessBuilder(command).start()) {
40+
var standardOutput = new StringJoiner("\n");
41+
var outputThread = Thread.ofVirtual().start(() -> {
4142
try (var reader = process.inputReader(UTF_8)) {
42-
reader.lines().forEach(output::add);
43-
} catch (IOException e) {
44-
LOGGER.at(Level.ERROR).setCause(e).log("Error while closing process output reader");
43+
reader.lines().forEach(standardOutput::add);
44+
} catch (IOException | UncheckedIOException e) {
45+
LOGGER.at(Level.ERROR).setCause(e).log("An error occurred using process output reader");
46+
}
47+
});
48+
49+
var standardError = new StringJoiner("\n");
50+
var errorThread = Thread.ofVirtual().start(() -> {
51+
try (var reader = process.errorReader(UTF_8)) {
52+
reader.lines().forEach(standardError::add);
53+
} catch (IOException | UncheckedIOException e) {
54+
LOGGER.at(Level.ERROR).setCause(e).log("An error occurred using process error reader");
4555
}
4656
});
4757

4858
var finished = process.waitFor(1, TimeUnit.MINUTES);
4959
if (!finished) {
5060
process.destroyForcibly();
51-
readerThread.join();
52-
throw new ProcessException("The command {} timed out after 1m\n{}", command[0], output.toString());
61+
outputThread.join();
62+
errorThread.join();
63+
LOGGER.at(Level.WARN).log("The command {} timed out after 1m: {}", command[0], standardError.toString());
64+
throw new ProcessException("The command {} timed out after 1m", command[0]);
5365
}
5466

55-
readerThread.join();
67+
outputThread.join();
68+
errorThread.join();
69+
5670
var exitCode = process.exitValue();
5771
if (exitCode != 0) {
58-
throw new ProcessException("The command {} exited with code {}\n{}", command[0], exitCode, output.toString());
72+
LOGGER.at(Level.WARN).log("The command {} exited with code {}: {}", command[0], exitCode, standardError.toString());
73+
throw new ProcessException("The command {} exited with code {}", command[0], exitCode);
5974
}
6075

61-
return output.toString();
76+
return standardOutput.toString();
6277
} catch (IOException e) {
6378
throw new ProcessException(e);
6479
} finally {

0 commit comments

Comments
 (0)