OpenOptions::custom_flags with O_NONBLOCK on pipe

I fail to create and open a pipe with O_NONBLOCK as shown by this program:

#![allow(dead_code, unused_macros, unused_variables, unused_assignments, unreachable_code)]
#![allow(unused_imports)]

extern crate libc;
use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;

use std::fs::File;
use std::error::Error;
use std::path::{Path,PathBuf};

type Result<T> = std::result::Result<T, Box<Error>>;

fn mkfifo(path: &PathBuf) -> Result<()> {
    std::fs::remove_file(&path).or::<()>(Ok(())).unwrap();
    let path_name = path.to_str().unwrap();
    let c_path = std::ffi::CString::new(path_name).unwrap();
    // Safe because c_path points to a valid C string.
    let status = unsafe { libc::mkfifo(c_path.as_ptr(), 0o644) };
    if status < 0 {
        Err(format!("mkfifo").into())
    } else {
        Ok(())
    }
}

fn new(fifo_path: PathBuf) -> Result<File> {
    println!("{:?}", fifo_path);
    let fifo_in = OpenOptions::new()
        .custom_flags(libc::O_NONBLOCK)
        .open(&fifo_path)?;
    println!("{:?}", fifo_in);
    let fifo_out = OpenOptions::new()
        .custom_flags(libc::O_NONBLOCK)
        .write(true)
        .open(&fifo_path)?;
    Ok(fifo_out)
}


fn main() {
    let p = PathBuf::from("x");
    mkfifo(&p).expect("bad mkfifo");
    let f = new(p);
    println!("{:?}", f);
}

This is the output:

semenzato@luigi:~/src/rust$ ./target/debug/main
"x"
Err(Os { code: 22, kind: InvalidInput, message: "Invalid argument" })

strace shows that open() is not even called so the failure cause isn't immediately clear. I did the equivalent operation (minus any errors) in previous programs in C, and that seems to work. Any suggestions on debugging this? Thanks!

Are you missing read(true) for fifo_in?

1 Like

Thank you vitalyd. This works fine with .read(true). Sorry for the spam!

1 Like