BurntSushi / rust-csv

A CSV parser for Rust, with Serde support.
The Unlicense
1.72k stars 219 forks source link

Writing to stdout/stderr from multiple threads results in split or mixed lines #320

Closed jpmckinney closed 1 year ago

jpmckinney commented 1 year ago

What version of the csv crate are you using?

1.2.1

Briefly describe the question, bug or feature request.

Writing to stdout/stderr from multiple threads results in split or mixed lines.

Include a complete program demonstrating a problem.

I'm using rayon. This avoids threading boilerplate. (That said, if the bug is specific to rayon, it's worth looking into, since rayon is a top-100 crate.)

// `extern` to be able to copy-paste into Rust Playground.
extern crate rayon;
use rayon::prelude::*;

fn main() {
    (1..10).par_bridge().for_each(|x| {
        let mut writer = csv::Writer::from_writer(std::io::stderr());
        for _ in 1..1000 {
            writer.serialize((x, "qwertyuiop", "asdfghjkl", "zxcvbnm")).unwrap();
        }
        writer.flush().unwrap();
    });
}
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"

[dependencies]
csv = "1.2"
rayon = "1.0"

What is the observed behavior of the code above?

You'll see lines like:

6,qwertyuiop,asdfghjkl,z9,qwertyuiop,asdfghjkl,zxcvbnm

Later, the rest of the line from the 6 thread will appear (coincidentally mixed with another line from the 9 thread):

9,qwertyxcvbnm

What is the expected or desired behavior of the code above?

Write a full line at once to stdout/stderr. println! and eprintln! manage (I don't know how.)

For example, cannot reproduce with:

// `extern` to be able to copy-paste into Rust Playground.
extern crate rayon;
use rayon::prelude::*;

fn main() {
    (1..10).par_bridge().for_each(|x| {
        for _ in 1..1000 {
            println!("{},{},{},{}", x, "qwertyuiop", "asdfghjkl", "zxcvbnm");
        }
    });
}