From 421ba2f15d1e7e39a4718d657b2534059a6cf660 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 20 Oct 2025 14:40:33 +0200 Subject: [PATCH 1/4] Bug: when raw-streams are used, ensure system streams are set up When --raw-streams are 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 fast at the place that would do system out before the thread with FastTerminal finishes. In other words, when --raw-streams are used, we cannot right now guarantee that system streams are already 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). --- .../java/org/apache/maven/cling/invoker/LookupInvoker.java | 5 +++++ 1 file changed, 5 insertions(+) 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..499a01999118 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,11 @@ protected final void createTerminal(C context) { context.terminal = MessageUtils.getTerminal(); context.closeables.add(MessageUtils::systemUninstall); MessageUtils.registerShutdownHook(); // safety belt + + if (context.options().rawStreams().orElse(false)) { + // to trigger FastTerminal; when embedded we want this (and sys in/out/err set up) ASAP; dummy call + context.terminal.getName(); + } } else { doConfigureWithTerminal(context, context.terminal); } From 80de9c87d5093b50950a9dfc562b1fe25e6d2c28 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 20 Oct 2025 14:48:12 +0200 Subject: [PATCH 2/4] Reword commend --- .../main/java/org/apache/maven/cling/invoker/LookupInvoker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 499a01999118..200358c8754d 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 @@ -325,7 +325,7 @@ protected final void createTerminal(C context) { MessageUtils.registerShutdownHook(); // safety belt if (context.options().rawStreams().orElse(false)) { - // to trigger FastTerminal; when embedded we want this (and sys in/out/err set up) ASAP; dummy call + // to trigger FastTerminal; with raw-streams we must do this ASAP (to have system in/out/err set up) context.terminal.getName(); } } else { From 2ef5f131d12b2747fa0a65f76a6495422ef1acf7 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 21 Oct 2025 12:19:46 +0200 Subject: [PATCH 3/4] Add more Make the hacks ONLY if embedded+raw-streams. Fix toolbox tool to implement proper expectation too. --- .../java/org/apache/maven/cling/invoker/LookupInvoker.java | 4 +++- .../apache/maven/cling/executor/internal/ToolboxTool.java | 6 ++++-- 2 files changed, 7 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 200358c8754d..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 @@ -324,7 +324,9 @@ protected final void createTerminal(C context) { context.closeables.add(MessageUtils::systemUninstall); MessageUtils.registerShutdownHook(); // safety belt - if (context.options().rawStreams().orElse(false)) { + // 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(); } 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..5b65c87c7ec2 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 @@ -160,8 +160,10 @@ private String validateOutput(boolean shave, ByteArrayOutputStream stdout, ByteA } // 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); + // 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; } From f1436135d4b54c0691e429cd677c5f9b2b1f1cc2 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 21 Oct 2025 12:57:21 +0200 Subject: [PATCH 4/4] Check stdout only As stderr will contain warnings on higher Java versions (guava and other; terminally deprecated method...) --- .../org/apache/maven/cling/executor/internal/ToolboxTool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5b65c87c7ec2..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,7 +159,7 @@ 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()) { + 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