CommandLine.execute() never flushes the out and err PrintWriter instances after a command's Callable.call() (or Runnable.run()) completes. This means output written via print() can be silently lost.
newPrintWriter() creates writers with autoFlush=true.
However it seems autoFlush only triggers on println(), printf(), and format(). Since execute() has no finally block that flushes the writers any data written via print() is lost when the JVM exits.
To reproduce:
@Command(name = "demo")
public class Demo implements Callable<Integer> {
@Spec CommandSpec spec;
@Override
public Integer call() {
spec.commandLine().getOut().print("hello"); // never appears
return 0;
}
public static void main(String[] args) {
System.exit(new CommandLine(new Demo()).execute(args));
}
}
Running produces no output. Changing print to println makes it work and adding an explicit flush() also works.
Expected behavior:
execute() should flush both getOut() and getErr() after command execution, similar to how handleUnhandled() already flushes getErr().
Proposed fix:
Add a finally block which flushes in execute?
Workaround that I applied on my end for now
CommandLine cmd = new CommandLine(new Demo());
CommandLine.IExecutionStrategy delegate = cmd.getExecutionStrategy();
cmd.setExecutionStrategy(parseResult -> {
try {
return delegate.execute(parseResult);
} finally {
parseResult.commandSpec().commandLine().getOut().flush();
parseResult.commandSpec().commandLine().getErr().flush();
}
});
I'm using 4.7.7 which I think is the latest, right?
CommandLine.execute() never flushes the
outanderrPrintWriter instances after a command's Callable.call() (or Runnable.run()) completes. This means output written via print() can be silently lost.newPrintWriter() creates writers with autoFlush=true.
However it seems autoFlush only triggers on println(), printf(), and format(). Since execute() has no finally block that flushes the writers any data written via print() is lost when the JVM exits.
To reproduce:
Running produces no output. Changing print to println makes it work and adding an explicit flush() also works.
Expected behavior:
execute() should flush both getOut() and getErr() after command execution, similar to how handleUnhandled() already flushes getErr().
Proposed fix:
Add a finally block which flushes in
execute?Workaround that I applied on my end for now
I'm using 4.7.7 which I think is the latest, right?