Skip to content

Commit ac05562

Browse files
committed
fix(ui): do not call setvbuf on Windows — size 0 aborts the process
The UCRT documents setvbuf's size as `2 <= size <= INT_MAX`. Zero goes through the invalid-parameter handler, whose default action terminates the process: 0xC0000409, which git-bash reports as a bare exit 127. The freshly built mcpp.exe died on `--version` with no output at all, right after a green build — the same mask mcpp#230 wore. Passing a real size instead would buy nothing: MSVCRT has no line buffering, it accepts _IOLBF and treats it as _IOFBF. Windows already gets the guarantee from ui::flush(), which every stdout-writing function in this module calls and which `mcpp test`'s result lines now route through. So the platform that cannot do this cheaply is also the one that does not need it — and its 4096-byte block was the smallest of the three to begin with. Line-flushing on Linux re-verified after the change: 421 individual writes for a 30-member workspace test, versus 3 block writes before this series.
1 parent 2f1bc1c commit ac05562

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

src/ui.cppm

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,24 @@ bool is_quiet() { return g_quiet; }
244244

245245
void flush() { std::fflush(stdout); }
246246

247-
void set_line_buffered() { std::setvbuf(stdout, nullptr, _IOLBF, 0); }
247+
void set_line_buffered() {
248+
#if defined(_WIN32)
249+
// Not on Windows, and not as a preference. The UCRT documents setvbuf's
250+
// size as `2 <= size <= INT_MAX`, and a zero goes through the
251+
// invalid-parameter handler, whose default action terminates the process:
252+
// 0xC0000409, which git-bash reports as a bare exit 127. The freshly built
253+
// mcpp.exe died on `--version` before printing anything.
254+
//
255+
// Passing a real size instead would buy nothing: MSVCRT has no line
256+
// buffering at all — it accepts _IOLBF and treats it as _IOFBF. Windows
257+
// gets the same guarantee from ui::flush(), which every stdout-writing
258+
// function here calls, so the platform that cannot do this cheaply is also
259+
// the one that does not need it: its 4096-byte block is the smallest of the
260+
// three anyway, and `mcpp test` routes its result lines through ui::plain.
261+
#else
262+
std::setvbuf(stdout, nullptr, _IOLBF, 0);
263+
#endif
264+
}
248265

249266
void status(std::string_view verb, std::string_view message) {
250267
if (g_quiet) return;

0 commit comments

Comments
 (0)