Fix preparer output routing to preserve stdout/stderr distinction#144356
Merged
mark-vieira merged 3 commits intoelastic:mainfrom Mar 17, 2026
Merged
Fix preparer output routing to preserve stdout/stderr distinction#144356mark-vieira merged 3 commits intoelastic:mainfrom
mark-vieira merged 3 commits intoelastic:mainfrom
Conversation
Collaborator
|
Pinging @elastic/es-core-infra (Team:Core/Infra) |
Merged
The ServerLauncher routes all preparer text output to stderr, breaking tools that expect --version/--help on stdout. Tag stderr-destined lines at the stream level so the launcher can dispatch them correctly. Untagged output defaults to stdout. Made-with: Cursor
83e5b66 to
ce74308
Compare
Replace line-based stderr tagging with a byte-level mode-switching protocol so that stdout/stderr routing is preserved even for partial-line output (e.g. print() without a trailing newline). Made-with: Cursor
rjernst
reviewed
Mar 16, 2026
| stdout.flush(); | ||
| stderr.flush(); | ||
| } catch (IOException e) { | ||
| // stream closed, nothing to do |
Member
There was a problem hiding this comment.
can we avoid swallowing ioexceptions? here and below
Contributor
Author
There was a problem hiding this comment.
Good catch. We now rethrow UncheckedIOException.
| * | ||
| * <p> The preparer uses an {@code OutputStreamMux} (in the cli-launcher module) to | ||
| * multiplex its stdout and stderr onto a single pipe. Mode byte {@link #STDOUT_MODE} | ||
| * ({@code 0x01}) switches to stdout; {@link #STDERR_MODE} ({@code 0x02}) switches to |
Member
There was a problem hiding this comment.
so this assumes that 0x01 and 0x02 never appear in the actual streams, right? can we guarantee that? (I think we can, unicode shouldn't have any dangling high bit 0 bytes and these are unprintable codes, but just want to be sure).
Contributor
Author
There was a problem hiding this comment.
Yeah. Assuming we aren't writing any non-unicode to the terminal here (which we shouldn't be).
Made-with: Cursor
michalborek
pushed a commit
to michalborek/elasticsearch
that referenced
this pull request
Mar 23, 2026
…astic#144356) * Fix preparer output routing to preserve stdout/stderr The ServerLauncher routes all preparer text output to stderr, breaking tools that expect --version/--help on stdout. Tag stderr-destined lines at the stream level so the launcher can dispatch them correctly. Untagged output defaults to stdout.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The recent ServerLauncher changes (#143712) route all preparer (server-cli) text output to stderr, breaking downstream tools that expect output like
--versionand--helpon stdout.This PR fixes the issue by multiplexing stdout and stderr onto a single pipe using byte-level mode switching, then demultiplexing in the launcher:
OutputStreamMuxin the preparer that replaces bothSystem.outandSystem.errwith mux channels writing to a single pipe. Mode byte0x01marks stdout,0x02marks stderr. Mode markers are only emitted on transitions, making same-channel writes zero-overhead.PreparerOutputPumpthat reads raw bytes, tracks the current mode, and routes data to the correct stream.This byte-level approach (as opposed to the earlier line-based tagging) correctly preserves stdout/stderr distinction even for partial-line output like
print()without a trailing newline (e.g. password prompts).Test plan
OutputStreamMux(mode emission, lazy switching, interleaved partial lines, UTF-8)PreparerOutputPump(mode switching, default mode, marker stripping)CliToolLauncherTestsverifying mode markers on stdout/stderr outputPackagingTestCase.assertElasticsearchFailureworkaround (no longer needed)