Skip to content
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

Reading from a pipe until done without hanging? #13

Open
simmel opened this issue Mar 22, 2022 · 4 comments
Open

Reading from a pipe until done without hanging? #13

simmel opened this issue Mar 22, 2022 · 4 comments

Comments

@simmel
Copy link

simmel commented Mar 22, 2022

Thanks for creating this abstraction!

I'm trying to read from a pipe on *NIX until the whole file has been sent.

E.g. until cat file > /tmp/my_pipe is done.

nix::unistd::mkfifo(Path::new(&args.path), stat::Mode::S_IRWXU).unwrap();
let content = fs::read_to_string(&args.path).unwrap();
println!("{:?}", content);

works (i.e. the program stops when cat file > /tmp/my_pipe is done) but not:

let mut pipe = Pipe::with_name(&args.path).unwrap();
let mut buffer = String::new();
let mut reader = std::io::BufReader::new(&mut pipe);
loop {
     match reader.read_line(&mut buffer) {
           Ok(bytes_read) => {
              println!("read bytes: {:?}", bytes_read);
              if bytes_read == 0 {
                  break;
             }
              println!("{:?}", buffer);

          }
         Err(err) => {
             println!("{:?}", err);
              //return Err(err);
         }
      };
}

I'm probably doing something wrong but maybe you can point me in the right direction?

@Eolu
Copy link
Owner

Eolu commented Mar 23, 2022

This looks like a bug in the library, not your code. Looks like somehow the EOF is not making it to read_line. I'll take a look into it

@Eolu
Copy link
Owner

Eolu commented Mar 27, 2022

While still not fixed, I believe the source of this bug has been found: Unix named pipes do not receive an EOF until all writers have closed their handles. In the current implementation, all handles are opened as R/W, meaning that the existence of any open read handle also prevents any EOF from coming through, which also breaks any function that depends on it (eg read_line). The only way to solve this is an API change: There's needs to be separate functions/structs for opening pipes for reading vs writing.

This also needs to result in some limitations to the cross-platform functionality of this crate: Windows names pipes must be opened in half-duplex rather than full-duplex, which means careful consideration needs to be made about how/when pipes are opened and dropped in order to for cross-platform functionality to be seamless. This crate is just not there yet. I still think it's possible to find a lowest-common-denominator set of functionality that works equivalently in either Unix or Windows environments, but the API and implementation will need to undergo some significant transformations to get there.

@simmel
Copy link
Author

simmel commented Apr 4, 2022

(seems that Github has lost my mail reply...)

I understand the implication of fixing this issue and I appreciate that you took the time to analyze it.

Is it possible for me to just close the write handle (since I won’t use it) or does that need code changes as well?

Thanks!

@simmel
Copy link
Author

simmel commented Oct 11, 2022 via email

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