Repository navigation
Buffer a glibc guest's piped stdout fully from the first line - #18
Open
buyemune-sys wants to merge 2 commits into
Open
buyemune-sys wants to merge 2 commits into
buyemune-sys wants to merge 2 commits into
Conversation
Security updates replaced libapparmor1 4.0.1really4.0.1-0ubuntu0.24.04.7 with .9 and libexpat1 2.6.1-2ubuntu0.4 with ubuntu0.6, and the pool kept only the new files, so the cold-cache Fetch x86_64 job answers 404 and every x86-64 job behind it is skipped. Both pins move to the versions noble-updates ships now; their SHA256s match the archive's Packages index. The other twelve pins are still served.
glibc settles stdout's buffering when the stream first allocates its buffer: line buffering for a terminal, full blocks for anything else. musl decides at the first flush instead. Until then stdout counts as line buffered, so the first line written to a pipe or file goes out on its own, ahead of anything the program wrote to stderr after it. That reorders merged output (`prog 2>&1 | ...`): LuaJIT's lj-586-debug-non-string-error test reads a debugger session through such a pipe and finds the printed value ahead of the prompt that preceded it. The bridge's __libc_start_main now makes glibc's decision before the guest's initializers run. A guest's own setvbuf still overrides it. The guest executable writes to stderr after its first stdout line, and the smoke run, which pipes stdout with stderr merged in, expects that line ahead of all of the guest's stdout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
buyemune-sys
force-pushed
the
fix/glibc-stdout-buffering
branch
from
October 20, 2026 08:11
74aa8d1 to
a6bfc07
Compare
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.
The problem
glibc settles stdout's buffering when the stream first allocates its buffer: line buffering for a terminal, full blocks for anything else. musl decides at the first flush (
ext/musl/src/stdio/__stdout_write.c:8). Until then stdout counts as line buffered, so the first line written to a pipe or file goes out on its own, ahead of whatever the program writes to stderr next:That reorders merged output. LuaJIT's
lj-586-debug-non-string-errortest reads adebug.debug()session through such a pipe, and under solo it finds the printed value ahead of the prompt that preceded it.The fix
The bridge's
__libc_start_main(lib/glibc_shim.cpp:2604) makes glibc's decision before the guest's initializers run: if stdout is not a terminal, it sets full buffering. A guest's ownsetvbufstill overrides it.Test
The guest executable writes
guest stderrright after its first stdout line. The smoke run pipes stdout with stderr merged in and expects that line ahead of all of the guest's stdout.On
main:solo run flushed the guest's piped stdout line by line. With the fix:./build testpasses.