Created
September 3, 2014 16:12
-
-
Save hpoul/83ff1a63c13cc49a4839 to your computer and use it in GitHub Desktop.
NuProcess - Possible race condition on linux with fast exiting processes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package playground; | |
| import java.nio.ByteBuffer; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.List; | |
| import java.util.concurrent.CompletableFuture; | |
| import java.util.concurrent.CompletionStage; | |
| import java.util.concurrent.ExecutionException; | |
| import com.zaxxer.nuprocess.NuAbstractProcessHandler; | |
| import com.zaxxer.nuprocess.NuProcess; | |
| import com.zaxxer.nuprocess.NuProcessBuilder; | |
| /** | |
| * Launching with: | |
| * java -jar nuprocessproblem.jar 1000 echo test | |
| * or | |
| * java -jar nuprocessproblem.jar 1000 bash -c "echo test" | |
| * produces on linux about ~ 5% failures | |
| * | |
| * java -jar nuprocessproblem.jar 1000 bash -c "sleep 0.01 ; echo test" | |
| * works 100% | |
| */ | |
| public class NuProcessProblem { | |
| public static void main(String[] args) { | |
| int count = 100; | |
| List<String> command = new ArrayList<>(); | |
| if (args.length > 0) { | |
| count = Integer.parseInt(args[0]); | |
| for (int i = 1 ; i < args.length ; i++) { | |
| command.add(args[i]); | |
| } | |
| } | |
| int success = 0, fail = 0; | |
| List<String> errors = new ArrayList<>(); | |
| for (int i = 0 ; i < count ; i++) { | |
| try { | |
| startEchoProcess(command).toCompletableFuture().get(); | |
| success++; | |
| } catch (InterruptedException | ExecutionException e) { | |
| errors.add(e.getLocalizedMessage()); | |
| e.printStackTrace(); | |
| fail++; | |
| } | |
| } | |
| System.out.println("All Errors: " + errors); | |
| System.out.println("Result: success: " + success + " / fail: " + fail); | |
| } | |
| public static CompletionStage<Void> startEchoProcess(List<String> command) { | |
| if (command.isEmpty()) { | |
| command = Arrays.asList("echo", "-i", "blubb", "-acodec", "libmp3lame", "-y", "asdf"); | |
| } | |
| CompletableFuture<Void> completableFuture = new CompletableFuture<>(); | |
| NuProcessBuilder builder = new NuProcessBuilder(command); | |
| builder.setProcessListener(new NuAbstractProcessHandler() { | |
| @Override | |
| public void onStdout(ByteBuffer buffer) { | |
| logOutput("STDOUT: ", buffer); | |
| } | |
| @Override | |
| public boolean onStdinReady(ByteBuffer buffer) { | |
| return false; | |
| } | |
| @Override | |
| public void onStderr(ByteBuffer buffer) { | |
| logOutput("STDERR: ", buffer); | |
| } | |
| @Override | |
| public void onStart(NuProcess nuProcess) { | |
| System.out.println("onStart"); | |
| } | |
| @Override | |
| public void onExit(int exitCode) { | |
| System.out.println("onExit: " + exitCode); | |
| if (exitCode == 0) { | |
| completableFuture.complete(null); | |
| } else { | |
| completableFuture.completeExceptionally(new RuntimeException("exited with code: " + exitCode)); | |
| } | |
| } | |
| private void logOutput(String prefix, ByteBuffer buffer) { | |
| if (buffer == null) { | |
| return; | |
| } | |
| byte[] buf = new byte[buffer.remaining()]; | |
| buffer.get(buf); | |
| System.out.println(prefix + " " + new String(buf).trim()); | |
| } | |
| }); | |
| NuProcess process = builder.start(); | |
| return completableFuture; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment