Skip to content

io::Stderr should be line-buffered by default, not unbuffered #64413

Open
@zackw

Description

@zackw

std::io::stderr does no buffering at all by default, which means that a Rust program that uses the most obvious way to print error messages (eprintln!) will make individual write syscalls not only for each call to the macro, but for each subcomponent of the formatted string:

$ cat test.rs
fn main() {
  eprint!("partial ");
  eprintln!("line");
  eprintln!("a one and a two and a {} and a {}", 3, 4.0);
}
$ rustc test.rs
$ strace -e trace=write sh -c 'exec ./test 2> /dev/null'
write(2, "partial ", 8)                 = 8
write(2, "line\n", 5)                   = 5
write(2, "a one and a two and a ", 22)  = 22
write(2, "3", 1)                        = 1
write(2, " and a ", 7)                  = 7
write(2, "4", 1)                        = 1
write(2, "\n", 1)                       = 1

This behavior is undesirable in any context where multiple programs might be emitting error messages to the same terminal, logfile, or whatever at the same time (for instance, make -j) because partial lines from different programs can get mixed up with each other. If stderr instead buffered up a full line and wrote it to the OS all at once, then different programs' output could only get mixed together on a line-by-line basis, which is usually much less confusing for a person reading the logs.

This behavior is also troublesome for programs that incrementally parse stderr output; for instance, it may be the reason why emacs' compilation-mode occasionally doesn't detect all of the diagnostics in cargo build output (I don't know if there's an existing bug report for this).

(There is a strong case for having eprint! flush out the partial line that it generates, but that could be handled inside of eprint!.)

(This is closely related to, but not the same as, #60673, which is about stdout. Block buffering is not normally appropriate for stderr, even when writing to a file.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions