diff options
| author | bors <bors@rust-lang.org> | 2018-05-17 02:05:39 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-05-17 02:05:39 +0000 |
| commit | b559710e58427213d6f82008206c22cf3d76b4c4 (patch) | |
| tree | d62ab7dd18ca9dd186257cbc398351281adf79ec /src/libstd/sys | |
| parent | 4208bd5ed8d2b62d151d759bcffec16f98248d53 (diff) | |
| parent | 3c261a4ea9d931d6af8562ab3c669a64cbf2c023 (diff) | |
| download | rust-b559710e58427213d6f82008206c22cf3d76b4c4.tar.gz rust-b559710e58427213d6f82008206c22cf3d76b4c4.zip | |
Auto merge of #50807 - kennytm:rollup, r=kennytm
Rollup of 17 pull requests Successful merges: - #50170 (Implement From for more types on Cow) - #50638 (Don't unconditionally set CLOEXEC twice on every fd we open on Linux) - #50656 (Fix `fn main() -> impl Trait` for non-`Termination` trait) - #50669 (rustdoc: deprecate `#![doc(passes, plugins, no_default_passes)]`) - #50726 (read2: Use inner function instead of closure) - #50728 (Fix rustdoc panic with `impl Trait` in type parameters) - #50736 (env: remove unwrap in examples in favor of try op) - #50740 (Remove LazyBTreeMap.) - #50752 (Add missing error codes in libsyntax-ext asm) - #50779 (Make mutable_noalias and arg_align_attributes be tracked) - #50787 (Fix run-make wasm tests) - #50788 (Fix an ICE when casting a nonexistent const) - #50789 (Ensure libraries built in stage0 have unique metadata) - #50793 (tidy: Add a check for empty UI test files) - #50797 (fix a typo in signed-integer::from_str_radix()) - #50808 (Stabilize num::NonZeroU*) - #50809 (GitHub: Stop treating Cargo.lock as a generated file.) Failed merges:
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/unix/fd.rs | 7 | ||||
| -rw-r--r-- | src/libstd/sys/unix/fs.rs | 41 | ||||
| -rw-r--r-- | src/libstd/sys/unix/pipe.rs | 37 |
3 files changed, 63 insertions, 22 deletions
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 67546d06b4e..4830e38d6a9 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -154,6 +154,13 @@ impl FileDesc { } } + #[cfg(target_os = "linux")] + pub fn get_cloexec(&self) -> io::Result<bool> { + unsafe { + Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) + } + } + #[cfg(not(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten", diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index a1ca839dc18..77968ffdedf 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -441,15 +441,48 @@ impl File { // Currently the standard library supports Linux 2.6.18 which did not // have the O_CLOEXEC flag (passed above). If we're running on an older - // Linux kernel then the flag is just ignored by the OS, so we continue - // to explicitly ask for a CLOEXEC fd here. + // Linux kernel then the flag is just ignored by the OS. After we open + // the first file, we check whether it has CLOEXEC set. If it doesn't, + // we will explicitly ask for a CLOEXEC fd for every further file we + // open, if it does, we will skip that step. // // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc // that we support, so we only do this on Linux currently. - if cfg!(target_os = "linux") { - fd.set_cloexec()?; + #[cfg(target_os = "linux")] + fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> { + use sync::atomic::{AtomicUsize, Ordering}; + + const OPEN_CLOEXEC_UNKNOWN: usize = 0; + const OPEN_CLOEXEC_SUPPORTED: usize = 1; + const OPEN_CLOEXEC_NOTSUPPORTED: usize = 2; + static OPEN_CLOEXEC: AtomicUsize = AtomicUsize::new(OPEN_CLOEXEC_UNKNOWN); + + let need_to_set; + match OPEN_CLOEXEC.load(Ordering::Relaxed) { + OPEN_CLOEXEC_UNKNOWN => { + need_to_set = !fd.get_cloexec()?; + OPEN_CLOEXEC.store(if need_to_set { + OPEN_CLOEXEC_NOTSUPPORTED + } else { + OPEN_CLOEXEC_SUPPORTED + }, Ordering::Relaxed); + }, + OPEN_CLOEXEC_SUPPORTED => need_to_set = false, + OPEN_CLOEXEC_NOTSUPPORTED => need_to_set = true, + _ => unreachable!(), + } + if need_to_set { + fd.set_cloexec()?; + } + Ok(()) + } + + #[cfg(not(target_os = "linux"))] + fn ensure_cloexec(_: &FileDesc) -> io::Result<()> { + Ok(()) } + ensure_cloexec(&fd)?; Ok(File(fd)) } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index ec9b6f17dca..0a5dccdddda 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -100,24 +100,6 @@ pub fn read2(p1: AnonPipe, // wait for either pipe to become readable using `poll` cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?; - // Read as much as we can from each pipe, ignoring EWOULDBLOCK or - // EAGAIN. If we hit EOF, then this will happen because the underlying - // reader will return Ok(0), in which case we'll see `Ok` ourselves. In - // this case we flip the other fd back into blocking mode and read - // whatever's leftover on that file descriptor. - let read = |fd: &FileDesc, dst: &mut Vec<u8>| { - match fd.read_to_end(dst) { - Ok(_) => Ok(true), - Err(e) => { - if e.raw_os_error() == Some(libc::EWOULDBLOCK) || - e.raw_os_error() == Some(libc::EAGAIN) { - Ok(false) - } else { - Err(e) - } - } - } - }; if fds[0].revents != 0 && read(&p1, v1)? { p2.set_nonblocking(false)?; return p2.read_to_end(v2).map(|_| ()); @@ -127,4 +109,23 @@ pub fn read2(p1: AnonPipe, return p1.read_to_end(v1).map(|_| ()); } } + + // Read as much as we can from each pipe, ignoring EWOULDBLOCK or + // EAGAIN. If we hit EOF, then this will happen because the underlying + // reader will return Ok(0), in which case we'll see `Ok` ourselves. In + // this case we flip the other fd back into blocking mode and read + // whatever's leftover on that file descriptor. + fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> { + match fd.read_to_end(dst) { + Ok(_) => Ok(true), + Err(e) => { + if e.raw_os_error() == Some(libc::EWOULDBLOCK) || + e.raw_os_error() == Some(libc::EAGAIN) { + Ok(false) + } else { + Err(e) + } + } + } + } } |
