-
Notifications
You must be signed in to change notification settings - Fork 469
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Josh Triplett <josh@joshtriplett.org>
- Loading branch information
1 parent
163eb8e
commit b030a29
Showing
5 changed files
with
188 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//! Adapted from: | ||
//! - https://doc.rust-lang.org/src/std/sys/unix/pipe.rs.html | ||
//! - https://doc.rust-lang.org/src/std/sys/unix/fd.rs.html#385 | ||
//! - https://github.com/rust-lang/rust/blob/master/library/std/src/sys/mod.rs#L57 | ||
//! - https://github.com/oconnor663/os_pipe.rs | ||
use std::fs::File; | ||
|
||
/// Open a new pipe and return a pair of [`File`] objects for the reader and writer. | ||
/// | ||
/// This corresponds to the `pipe2` library call on Posix and the | ||
/// `CreatePipe` library call on Windows (though these implementation | ||
/// details might change). These pipes are non-inheritable, so new child | ||
/// processes won't receive a copy of them unless they're explicitly | ||
/// passed as stdin/stdout/stderr. | ||
pub fn pipe() -> std::io::Result<(File, File)> { | ||
sys::pipe() | ||
} | ||
|
||
#[cfg(unix)] | ||
#[path = "os_pipe/unix.rs"] | ||
mod sys; | ||
|
||
#[cfg(windows)] | ||
#[path = "os_pipe/windows.rs"] | ||
mod sys; | ||
|
||
#[cfg(all(not(unix), not(windows)))] | ||
compile_error!("Only unix and windows support os_pipe!"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
use std::{ | ||
fs::File, | ||
io, | ||
os::{raw::c_int, unix::io::FromRawFd}, | ||
}; | ||
|
||
pub(super) fn pipe() -> io::Result<(File, File)> { | ||
let mut fds = [0; 2]; | ||
|
||
// The only known way right now to create atomically set the CLOEXEC flag is | ||
// to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9 | ||
// and musl 0.9.3, and some other targets also have it. | ||
#[cfg(any( | ||
target_os = "dragonfly", | ||
target_os = "freebsd", | ||
target_os = "linux", | ||
target_os = "netbsd", | ||
target_os = "openbsd", | ||
target_os = "redox" | ||
))] | ||
{ | ||
unsafe { | ||
cvt(libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC))?; | ||
} | ||
} | ||
|
||
#[cfg(not(any( | ||
target_os = "dragonfly", | ||
target_os = "freebsd", | ||
target_os = "linux", | ||
target_os = "netbsd", | ||
target_os = "openbsd", | ||
target_os = "redox" | ||
)))] | ||
{ | ||
unsafe { | ||
cvt(libc::pipe(fds.as_mut_ptr()))?; | ||
} | ||
|
||
cloexec::set_cloexec(fds[0])?; | ||
cloexec::set_cloexec(fds[1])?; | ||
} | ||
|
||
unsafe { Ok((File::from_raw_fd(fds[0]), File::from_raw_fd(fds[1]))) } | ||
} | ||
|
||
fn cvt(t: c_int) -> io::Result<c_int> { | ||
if t == -1 { | ||
Err(io::Error::last_os_error()) | ||
} else { | ||
Ok(t) | ||
} | ||
} | ||
|
||
#[cfg(not(any( | ||
target_os = "dragonfly", | ||
target_os = "freebsd", | ||
target_os = "linux", | ||
target_os = "netbsd", | ||
target_os = "openbsd", | ||
target_os = "redox" | ||
)))] | ||
mod cloexec { | ||
use super::{c_int, cvt, io}; | ||
|
||
#[cfg(not(any( | ||
target_env = "newlib", | ||
target_os = "solaris", | ||
target_os = "illumos", | ||
target_os = "emscripten", | ||
target_os = "fuchsia", | ||
target_os = "l4re", | ||
target_os = "linux", | ||
target_os = "haiku", | ||
target_os = "redox", | ||
target_os = "vxworks", | ||
target_os = "nto", | ||
)))] | ||
pub(super) fn set_cloexec(fd: c_int) -> io::Result<()> { | ||
unsafe { | ||
cvt(libc::ioctl(fd, libc::FIOCLEX))?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
#[cfg(any( | ||
all( | ||
target_env = "newlib", | ||
not(any(target_os = "espidf", target_os = "horizon")) | ||
), | ||
target_os = "solaris", | ||
target_os = "illumos", | ||
target_os = "emscripten", | ||
target_os = "fuchsia", | ||
target_os = "l4re", | ||
target_os = "linux", | ||
target_os = "haiku", | ||
target_os = "redox", | ||
target_os = "vxworks", | ||
target_os = "nto", | ||
))] | ||
pub(super) fn set_cloexec(fd: c_int) -> io::Result<()> { | ||
unsafe { | ||
let previous = cvt(libc::fcntl(fd, libc::F_GETFD))?; | ||
let new = previous | libc::FD_CLOEXEC; | ||
if new != previous { | ||
cvt(libc::fcntl(fd, libc::F_SETFD, new))?; | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
// FD_CLOEXEC is not supported in ESP-IDF and Horizon OS but there's no need to, | ||
// because neither supports spawning processes. | ||
#[cfg(any(target_os = "espidf", target_os = "horizon"))] | ||
pub(super) fn set_cloexec(_fd: c_int) -> io::Result<()> { | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use std::{fs::File, io, os::windows::prelude::*, ptr}; | ||
use windows_sys::Win32::{Foundation::INVALID_HANDLE_VALUE, System::Pipes::CreatePipe}; | ||
|
||
/// NOTE: These pipes do not support IOCP. | ||
/// | ||
/// If IOCP is needed, then you might want to emulate | ||
/// anonymous pipes with CreateNamedPipe, as Rust's stdlib does. | ||
pub(super) fn pipe() -> io::Result<(File, File)> { | ||
let mut read_pipe = INVALID_HANDLE_VALUE; | ||
let mut write_pipe = INVALID_HANDLE_VALUE; | ||
|
||
let ret = unsafe { CreatePipe(&mut read_pipe, &mut write_pipe, ptr::null_mut(), 0) }; | ||
|
||
if ret == 0 { | ||
Err(io::Error::last_os_error()) | ||
} else { | ||
unsafe { | ||
Ok(( | ||
File::from_raw_handle(read_pipe as RawHandle), | ||
File::from_raw_handle(write_pipe as RawHandle), | ||
)) | ||
} | ||
} | ||
} |