Skip to content

fix(libc): flush line-buffered output on Windows - #5394

Closed
MarcZX10 wants to merge 3 commits into
boykopovar:mainfrom
MarcZX10:codex/setvbuf-line-buffering-5391
Closed

MarcZX10 wants to merge 3 commits into
boykopovar:mainfrom
MarcZX10:codex/setvbuf-line-buffering-5391

Conversation

@MarcZX10

Copy link
Copy Markdown
Contributor

What

Carries Hussein Kadhim's Windows line-buffering fix from #5391, preserving his commit authorship. Windows' CRT treats _IOLBF as fully buffered, so guest stream writes now flush through the last newline while leaving the remaining tail buffered. The host stream remains buffered; the implementation covers the guest byte, string, formatted, wide and standard-output write paths and holds the stream lock for each line-buffered write. The flag resets when freopen or close replaces the stream and when a later setvbuf changes the mode. The test checks the Windows emulation flag on Windows and native _IOLBF behavior on Linux.

Tested

  • Linux (Ubuntu 24.04, GCC 12.2.0, Ninja, Release): built guest_standard_stream_tests and file_streams_tests; guest_standard_streams and file_streams passed (2/2).
  • Windows: the issue author reports the new line-buffering tests and both CTest cases pass on the proposed fix branch. I did not run a Windows build.
  • tools/check_conventions.py --base upstream/main and git diff --check pass.

Checklist

  • Based on current main; no open PR implements line buffering
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical-debt comments
  • Unimplemented paths throw; no stubs added
  • No notes, investigation files or images added to the repository
  • No third-party code added
  • Generic behavior, not title-specific
  • Depends on: fix(libc): build the host-facing libc code on macOS #4627 (overlapping putc_unlocked portability edit) and fix(libc): return a newline from puts like FreeBSD #4804 (overlapping puts return-value edit); resolve/rebase after those land
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

The Windows CRT treats _IOLBF as _IOFBF, so a stream a guest set to line buffering kept its output until the buffer filled or the stream closed, where FreeBSD writes it at each newline. setvbuf now maps line buffering to unbuffered output on Windows and the difference is listed in the technical debt.
…newline on Windows

Mapping line buffering to unbuffered output made every write a system call. The stream now stays fully buffered and the guest stream functions write it out up to the last newline, as FreeBSD does.
…t the mode on reopen

A line-buffered write was three separate locked calls, so two threads could interleave inside one call. The stream lock is now held for the whole write. freopen and fclose also clear the line-buffered flag, and the technical debt entry states how the guest buffer is used.
@likecrank-dotcom

Copy link
Copy Markdown

Independent Windows validation by OpenAI Codex (AI-assisted). No code changes were made to this PR.

Validated PR head 647e18497f087e942b9f89c01d6b5a0d4c15eee6 on Windows 11 Pro (build 26100) with WinLibs MinGW GCC 15.2.0 and CMake 4.4.4. Built guest_standard_stream_tests and file_streams_tests; CTest guest_standard_streams and file_streams each passed five consecutive runs (10/10 executions). tools/check_conventions.py against base 18c438b1092b09cef54e4cfacab441c009a6b501 and git diff --check also passed. This was a focused Windows build/test, not a full build or game run.

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#4804 core/libs/prx/libc/src/Formatting.cpp L544

@xXPBSXx

xXPBSXx commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Windows 10 (19045), MinGW-w64 GCC 15.2.0, Release, -j4: head 647e18497 of this PR merged onto main 19785b50e (clean merge, 8 files).

  • guest_standard_streams (0.79 s) and guest_formatting (0.16 s) pass (2 of 2, ctest).
  • A run without the change cannot show the behaviour: with the six product files taken back to main (and the two new headers removed) the new test does not compile (GuestStandardStreams.cpp:247 and :262: class FileStream has no member named IsLineBuffered), so the new test checks an interface that main lacks and fails to build there; a behavioural red run was not possible with this test.
  • Not run: Linux, a console, a title.

AI-assisted (Claude Code).

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title is known to reach this. With the queue at 700+ open PRs, please hold off on new PRs that don't name a title needing the change until it's down. If a title stops on this on current main, reopen with the title ID and the log line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants