Skip to content

Writing to stdout with write() changed behavior between version 1.47 and >= 1.48 #83528

Closed
@sdragic

Description

@sdragic

I'm not sure this is worth reporting, but it has caused confusion at least once, so maybe it makes sense to be documented somewhere.

When writing to stdout with write(), write will return smaller number bytes than direct write() call would do in some cases. Here is example code:

use std::io::{self, Write};

fn main() {
    let mut a = ['a' as u8; 2048];
    eprintln!("{}", a.len());
    eprintln!("{:?}", io::stdout().write(&a));
    a[50] = '\n' as u8;
    eprintln!("{:?}", io::stdout().write(&a));
}

Rustc 1.47 gives expected result:

#./main > /dev/null
2048
Ok(2048)
Ok(2048)

This is also in accordance with similar programs written in C, Python and Rust using libc::write().

However rustc 1.48 and greater return this:

#./main > /dev/null
2048
Ok(2048)
Ok(1075)

This is technically not a bug, but IMHO it is unexpected behavior. Rust docs says this:

This function will attempt to write the entire contents of buf, but the entire write may not succeed, or the write may also generate an error. A call to write represents at most one attempt to write to any wrapped object.

I'm aware "wrapped object" here is some internal std library structure, but most people would expect it should behave similarly to underlying system write().

man 2 write says:

The number of bytes written may be less than count if, for example, there is insufficient space on the underlying physical medium, or the RLIMIT_FSIZE resource limit is encountered (see setr‐limit(2)), or the call was interrupted by a signal handler after having written less than count bytes.

As I understand this, returning less than count should be affected only by OS state and not by content of data (newline in this case).

This behavior seems to be introduced with PR #72808, and pending PR #78515 seems to revert behavior to expected.

Just a disclaimer, I do not condone use of unchecked write(). Reason for reporting this is inconsistency between io::stdout().write() and similar approaches.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`P-lowLow priorityT-libsRelevant to the library 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