Skip to content

Commit

Permalink
refactor: make dup3 wrapper call the real dup3 (#2268)
Browse files Browse the repository at this point in the history
* refactor: make dup3 wrapper call the real dup3

* fix imports

* respond to review
  • Loading branch information
SteveLauC committed Jan 6, 2024
1 parent 3195d9e commit aeea7cf
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 20 deletions.
1 change: 1 addition & 0 deletions changelog/2268.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Changed the `dup3` wrapper to perform a real call to `dup3` instead of emulating it via `dup2` and `fcntl` to get rid of race condition
1 change: 1 addition & 0 deletions changelog/2268.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removed the `dup3` wrapper on macOS, which was emulated via `dup2` and `fcntl` and could cause a race condition. The `dup3` system call is not supported on macOS.
42 changes: 22 additions & 20 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,17 @@ use crate::fcntl::at_rawfd;
use crate::fcntl::AtFlags;

#[cfg(feature = "fs")]
use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag};
#[cfg(any(
linux_android,
freebsdlike,
solarish,
netbsdlike,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "hurd",
target_os = "redox",
))]
use crate::fcntl::OFlag;
#[cfg(all(feature = "fs", bsd))]
use crate::sys::stat::FileFlag;
#[cfg(feature = "fs")]
Expand Down Expand Up @@ -426,30 +436,22 @@ pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
}

/// Create a new copy of the specified file descriptor using the specified fd
/// and flags (see [dup(2)](https://man7.org/linux/man-pages/man2/dup.2.html)).
/// and flags (see [`dup(2)`](https://man7.org/linux/man-pages/man2/dup.2.html)).
///
/// This function behaves similar to `dup2()` but allows for flags to be
/// specified.
#[cfg(any(
netbsdlike,
solarish,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",
target_os = "linux"
))]
pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
dup3_polyfill(oldfd, newfd, flags)
}
let res = unsafe { libc::dup3(oldfd, newfd, flags.bits()) };

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
if oldfd == newfd {
return Err(Errno::EINVAL);
}

let fd = dup2(oldfd, newfd)?;

if flags.contains(OFlag::O_CLOEXEC) {
if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) {
let _ = close(fd);
return Err(e);
}
}

Ok(fd)
Errno::result(res)
}

/// Change the current working directory of the calling process (see
Expand Down

0 comments on commit aeea7cf

Please sign in to comment.