pal/unix/
pipe.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use super::SyscallResult;
5use std::fs::File;
6use std::io::Result;
7use std::os::unix::prelude::*;
8
9/// Creates a connected pair of pipes, returning (read, write).
10pub fn pair() -> Result<(File, File)> {
11    // SAFETY: calling C APIs as documented, with no special requirements.
12    unsafe {
13        let mut fds = [0; 2];
14        #[cfg(target_os = "linux")]
15        {
16            // Use pipe2 to set O_CLOEXEC atomically with pipe creation.
17            libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC).syscall_result()?;
18        }
19        #[cfg(not(target_os = "linux"))]
20        {
21            // Create the pipes and then set O_CLOEXEC as a separate step since
22            // pipe2 is not available.
23            //
24            // N.B. There is a race window here where the pipe will be inherited
25            //      by a child process if the fork occurs right after this call
26            //      before O_CLOEXEC is set.
27            libc::pipe(fds.as_mut_ptr()).syscall_result()?;
28            libc::fcntl(fds[0], libc::F_SETFL, libc::O_CLOEXEC)
29                .syscall_result()
30                .unwrap();
31            libc::fcntl(fds[1], libc::F_SETFL, libc::O_CLOEXEC)
32                .syscall_result()
33                .unwrap();
34        }
35        Ok((File::from_raw_fd(fds[0]), File::from_raw_fd(fds[1])))
36    }
37}
38
39/// Sets a file's nonblocking state.
40pub fn set_nonblocking(file: &File, nonblock: bool) -> Result<()> {
41    // SAFETY: the fd is owned, and changing the nonblocking state should not
42    // result in any memory safety issues since it just changes the conditions
43    // under which an IO will fail.
44    unsafe {
45        let mut flags = libc::fcntl(file.as_raw_fd(), libc::F_GETFL).syscall_result()?;
46        if nonblock {
47            flags |= libc::O_NONBLOCK;
48        } else {
49            flags &= !libc::O_NONBLOCK;
50        }
51        libc::fcntl(file.as_raw_fd(), libc::F_SETFL, flags).syscall_result()?;
52    }
53    Ok(())
54}