From 29484502829b98f7ac8b8445f75c3d71dd79dbaf Mon Sep 17 00:00:00 2001 From: Zach Reizner Date: Wed, 28 Mar 2018 15:54:04 -0700 Subject: [PATCH] sys_util: add function for creating pipe pairs Rust's libstd only supports creating socket pairs or pipes for spawning processes. This change supports creating a unidirectional pipe pair for any purpose. BUG=chromium:793688 TEST=None Change-Id: Ie148735f18c5b8859d8981b9035d87f806a487ff Reviewed-on: https://chromium-review.googlesource.com/985614 Commit-Ready: Zach Reizner Tested-by: Zach Reizner Reviewed-by: Chirantan Ekbote Reviewed-by: Zach Reizner Reviewed-by: Dylan Reid --- sys_util/src/lib.rs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/sys_util/src/lib.rs b/sys_util/src/lib.rs index e1a502631c..d9c5825bfb 100644 --- a/sys_util/src/lib.rs +++ b/sys_util/src/lib.rs @@ -57,11 +57,12 @@ pub use guest_memory::Error as GuestMemoryError; pub use signalfd::Error as SignalFdError; use std::ffi::CStr; -use std::os::unix::io::AsRawFd; +use std::fs::File; +use std::os::unix::io::{AsRawFd, FromRawFd}; use std::ptr; -use libc::{kill, syscall, sysconf, waitpid, c_long, pid_t, uid_t, gid_t, _SC_PAGESIZE, - SIGKILL, WNOHANG}; +use libc::{kill, syscall, sysconf, waitpid, pipe2, c_long, pid_t, uid_t, gid_t, _SC_PAGESIZE, + SIGKILL, WNOHANG, O_CLOEXEC}; use syscall_defines::linux::LinuxSyscall::SYS_getpid; @@ -188,3 +189,26 @@ pub fn kill_process_group() -> Result<()> { unreachable!(); } } + +/// Spawns a pipe pair where the first pipe is the read end and the second pipe is the write end. +/// +/// If `close_on_exec` is true, the `O_CLOEXEC` flag will be set during pipe creation. +pub fn pipe(close_on_exec: bool) -> Result<(File, File)> { + let flags = if close_on_exec { O_CLOEXEC } else { 0 }; + let mut pipe_fds = [-1; 2]; + // Safe because pipe2 will only write 2 element array of i32 to the given pointer, and we check + // for error. + let ret = unsafe { pipe2(&mut pipe_fds[0], flags) }; + if ret == -1 { + errno_result() + } else { + // Safe because both fds must be valid for pipe2 to have returned sucessfully and we have + // exclusive ownership of them. + Ok(unsafe { + ( + File::from_raw_fd(pipe_fds[0]), + File::from_raw_fd(pipe_fds[1]) + ) + }) + } +}