Skip to content

Stdout does panic in pipe #35108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gemmarx opened this issue Jul 29, 2016 · 5 comments
Closed

Stdout does panic in pipe #35108

gemmarx opened this issue Jul 29, 2016 · 5 comments

Comments

@gemmarx
Copy link

gemmarx commented Jul 29, 2016

In a 64-bit Linux box, the code below fails to write, and dies with a panic message only in a pipeline.

fn main() {
    use std::io::Write;

    let buf = "\n".as_bytes();
    for _ in 1..2000 {
        std::io::stdout().write(buf).unwrap();
    }
}
#This is ok.
$ rustc main.rs
$ ./main

#However, this calls a panic.
$ ./main | head -0
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 32, message: "Broken pipe" } }', ../src/libcore/result.rs:788
note: Run with `RUST_BACKTRACE=1` for a backtrace.

On the other hand, following two codes work with no trouble.

fn main() {
    use std::io::Write;

    let buf = "\n".as_bytes();
    for _ in 1..100 {
        std::io::stdout().write(buf).unwrap();
    }
}
fn main() {
    use libc::{c_int, size_t, c_void};

    let fd: c_int = 1;
    let buf = "\n".as_bytes();
    for _ in 1..2000 { unsafe {
        libc::write(fd,
                    buf.as_ptr() as *const c_void,
                    buf.len() as size_t);
    } }
}

What's happened?
It seems to be a buggy behaviour.
( rustc version is 1.12.0-nightly (feeca94 2016-07-26) )

@nagisa
Copy link
Member

nagisa commented Jul 29, 2016

As the message: "Broken pipe" implies, the stuff you’re piping into exits before your code finishes writing all your newlines.

The 2nd program likely finishes because it manages to write all of its stuff before head -0 exits. The 3rd program has different behaviour from the 1st or 2nd programs – it does not check the return code of libc::write, essentially ignoring the errors.

It seems to me that its working as it should be working.

@gemmarx
Copy link
Author

gemmarx commented Jul 29, 2016

Oh, thank you very much. I get it.

It sounds natural to handle exceptions neatly when bytes to write are to be greater than the buffer size of pipeline (maybe 1024?).

This means that print! or write! macro family is not good to use in pipeline because they cannot catch the errors, right?

@nagisa
Copy link
Member

nagisa commented Jul 29, 2016

write! allows you to handle the errors just fine (it returns a Result). print! does not.

@gemmarx
Copy link
Author

gemmarx commented Jul 29, 2016

That reminds me!

Thank you, nagisa-san.

@gemmarx
Copy link
Author

gemmarx commented Jul 29, 2016

In my short research, "wc" command in coreutils projict and exa at least have this panic problem.
They have lost some values as a filter command.
There could be more appropriate affordance for Stdout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants