Skip to content

Commit 0eb50a0

Browse files
committed
Better comments for set_aux_fd
1 parent 8ed919c commit 0eb50a0

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

src/tools/run-make-support/src/command.rs

+25-10
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ impl Command {
105105
}
106106

107107
/// Set an auxiliary stream passed to the process, besides the stdio streams.
108+
///
109+
/// Use with caution - ideally, only set one aux fd; if there are multiple,
110+
/// their old `fd` may overlap with another's `newfd`, and thus will break.
111+
/// If you need more than 1 auxiliary file descriptor, rewrite this function
112+
/// to be able to support that.
108113
#[cfg(unix)]
109114
pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>(
110115
&mut self,
@@ -114,18 +119,28 @@ impl Command {
114119
use std::os::fd::AsRawFd;
115120
use std::os::unix::process::CommandExt;
116121

122+
let cvt = |x| if x == -1 { Err(std::io::Error::last_os_error()) } else { Ok(()) };
123+
117124
let fd = fd.into();
118-
unsafe {
119-
self.cmd.pre_exec(move || {
120-
let fd = fd.as_raw_fd();
121-
let ret = if fd == newfd {
122-
libc::fcntl(fd, libc::F_SETFD, 0)
123-
} else {
124-
libc::dup2(fd, newfd)
125-
};
126-
if ret == -1 { Err(std::io::Error::last_os_error()) } else { Ok(()) }
127-
});
125+
if fd.as_raw_fd() == newfd {
126+
// if fd is already where we want it, just turn off FD_CLOEXEC
127+
// SAFETY: io-safe: we have ownership over fd
128+
cvt(unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_SETFD, 0) })
129+
.expect("disabling CLOEXEC failed");
130+
// we still unconditionally set the pre_exec function, since it captures
131+
// `fd`, and we want to ensure that it stays open until the fork
128132
}
133+
let pre_exec = move || {
134+
if fd.as_raw_fd() != newfd {
135+
// set newfd to point to the same file as fd
136+
// SAFETY: io-"safe": newfd is. not necessarily an unused fd.
137+
// however, we're
138+
cvt(unsafe { libc::dup2(fd.as_raw_fd(), newfd) })?;
139+
}
140+
Ok(())
141+
};
142+
// SAFETY: dup2 is pre-exec-safe
143+
unsafe { self.cmd.pre_exec(pre_exec) };
129144
self
130145
}
131146

src/tools/run-make-support/src/macros.rs

+5
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ macro_rules! impl_common_helpers {
8181
}
8282

8383
/// Set an auxiliary stream passed to the process, besides the stdio streams.
84+
///
85+
/// Use with caution - ideally, only set one aux fd; if there are multiple,
86+
/// their old `fd` may overlap with another's `newfd`, and thus will break.
87+
/// If you need more than 1 auxiliary file descriptor, rewrite this function
88+
/// to be able to support that.
8489
#[cfg(unix)]
8590
pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>(
8691
&mut self,

0 commit comments

Comments
 (0)