From c7f63b0bf2c70ae014b9ef54b75040ab550c52ca Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 21 Oct 2025 13:35:02 +0200 Subject: [PATCH] Bug: when raw-streams are used, ensure system streams are set up (#11303) When `--raw-streams` is used (especially when combined with options like `--quiet` and `-DforceStdout`) there is no guarantee that anything touches terminal. Hence, in case of embedded executor it is quite possible that cached/warm code arrives quickly at the place that would do system out **before** the thread with `FastTerminal` finishes system install. In other words, when `--raw-streams` are used, we cannot guarantee that system streams are already properly set up. This PR changes that, and makes sure (by triggering a dummy call to terminal), at the cost of "jline3 install lag" for CLI invocation. OTOH, this lag in case of embedded executors does not exists (it exists only on first invocation). My suspicion that this is the cause of IT instability issues, when Verifier used Toolbox output ends up on Surefire stdout and not on "grabbed" output, as simply streams are not yet set up properly. Also, this usually happens "around the second half" of ITs, when cached and warmed up embedded instance is already uber optimized. --- .../org/apache/maven/cling/invoker/LookupInvoker.java | 7 +++++++ .../apache/maven/cling/executor/internal/ToolboxTool.java | 8 +++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java index 0d5e5caa6411..50448a8ade38 100644 --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java @@ -323,6 +323,13 @@ protected final void createTerminal(C context) { context.terminal = MessageUtils.getTerminal(); context.closeables.add(MessageUtils::systemUninstall); MessageUtils.registerShutdownHook(); // safety belt + + // when we use embedded executor AND --raw-streams, we must ENSURE streams are properly set up + if (context.invokerRequest.embedded() + && context.options().rawStreams().orElse(false)) { + // to trigger FastTerminal; with raw-streams we must do this ASAP (to have system in/out/err set up) + context.terminal.getName(); + } } else { doConfigureWithTerminal(context, context.terminal); } diff --git a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/ToolboxTool.java b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/ToolboxTool.java index ebdd3ac2a512..ad2569a84910 100644 --- a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/ToolboxTool.java +++ b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/ToolboxTool.java @@ -159,9 +159,11 @@ private String validateOutput(boolean shave, ByteArrayOutputStream stdout, ByteA result = result.replace("\n", "").replace("\r", ""); } // sanity checks: stderr has any OR result is empty string (no method should emit empty string) - if (stderr.size() > 0 || result.trim().isEmpty()) { - System.err.println( - "Unexpected stdout[" + stdout.size() + "]=" + stdout + "; stderr[" + stderr.size() + "]=" + stderr); + if (result.trim().isEmpty()) { + // see bug https://github.com/apache/maven/pull/11303 Fail in this case + // tl;dr We NEVER expect empty string as output from this tool; so fail here instead to chase ghosts + throw new IllegalStateException("Empty output from Toolbox; stdout[" + stdout.size() + "]=" + stdout + + "; stderr[" + stderr.size() + "]=" + stderr); } return result; }