Skip to content

Commit 482fa51

Browse files
coolreader18Oneirical
authored andcommitted
Better comments for set_aux_fd
1 parent f6f9e10 commit 482fa51

File tree

4 files changed

+34
-18
lines changed

4 files changed

+34
-18
lines changed

src/tools/run-make-support/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,3 @@ gimli = "0.31.0"
1313
libc = "0.2"
1414
build_helper = { path = "../build_helper" }
1515
serde_json = "1.0"
16-
libc = "0.2"

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

+27-10
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ impl Command {
152152
}
153153

154154
/// Set an auxiliary stream passed to the process, besides the stdio streams.
155+
/// Use with caution - ideally, only set one aux fd; if there are multiple,
156+
/// their old `fd` may overlap with another's `newfd`, and may break.
157+
//FIXME: If more than 1 auxiliary file descriptor is needed, this function
158+
// should be rewritten.
155159
#[cfg(unix)]
156160
pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>(
157161
&mut self,
@@ -161,18 +165,31 @@ impl Command {
161165
use std::os::fd::AsRawFd;
162166
use std::os::unix::process::CommandExt;
163167

168+
let cvt = |x| if x == -1 { Err(std::io::Error::last_os_error()) } else { Ok(()) };
169+
164170
let fd = fd.into();
165-
unsafe {
166-
self.cmd.pre_exec(move || {
167-
let fd = fd.as_raw_fd();
168-
let ret = if fd == newfd {
169-
libc::fcntl(fd, libc::F_SETFD, 0)
170-
} else {
171-
libc::dup2(fd, newfd)
172-
};
173-
if ret == -1 { Err(std::io::Error::last_os_error()) } else { Ok(()) }
174-
});
171+
if fd.as_raw_fd() == newfd {
172+
// if the new file descriptor is already the same as fd, just turn off FD_CLOEXEC
173+
// SAFETY: io-safe: fd is already owned.
174+
cvt(unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_SETFD, 0) })
175+
.expect("disabling CLOEXEC failed");
176+
// The pre_exec function should be unconditionally set, since it captures
177+
// `fd`, and this ensures that it stays open until the fork
175178
}
179+
let pre_exec = move || {
180+
if fd.as_raw_fd() != newfd {
181+
// SAFETY: io-"safe": newfd is not necessarily an unused fd.
182+
// However, we're ensuring that newfd will now refer to the same file descriptor
183+
// as fd, which is safe as long as we manage the lifecycle of both descriptors
184+
// correctly. This operation will replace the file descriptor referred to by newfd
185+
// with the one from fd, allowing for shared access to the same underlying file or
186+
// resource.
187+
cvt(unsafe { libc::dup2(fd.as_raw_fd(), newfd) })?;
188+
}
189+
Ok(())
190+
};
191+
// SAFETY: dup2 is pre-exec-safe
192+
unsafe { self.cmd.pre_exec(pre_exec) };
176193
self
177194
}
178195

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

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

8383
/// Set an auxiliary stream passed to the process, besides the stdio streams.
84+
/// Use with caution - ideally, only set one aux fd; if there are multiple,
85+
/// their old `fd` may overlap with another's `newfd`, and may break.
86+
//FIXME: If more than 1 auxiliary file descriptor is needed, this function
87+
// should be rewritten.
8488
#[cfg(unix)]
8589
pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>(
8690
&mut self,

tests/run-make/jobserver-error/rmake.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,20 @@
44
// and errors are printed instead in case of a wrong jobserver.
55
// See https://github.com/rust-lang/rust/issues/46981
66

7-
// FIXME(Oneirical): The original test included this memo:
8-
// # Note that by default, the compiler uses file descriptors 0 (stdin), 1 (stdout), 2 (stderr),
9-
// # but also 3 and 4 for either end of the ctrl-c signal handler self-pipe.
10-
117
// FIXME(Oneirical): only-linux ignore-cross-compile
128

13-
use run_make_support::{diff, rfs, rustc};
9+
use run_make_support::{diff, rustc};
1410

1511
fn main() {
1612
let out = rustc()
17-
.stdin("fn main() {}")
13+
.stdin_buf(("fn main() {}").as_bytes())
1814
.env("MAKEFLAGS", "--jobserver-auth=5,5")
1915
.run_fail()
2016
.stderr_utf8();
2117
diff().expected_file("cannot_open_fd.stderr").actual_text("actual", out).run();
2218

2319
let out = rustc()
24-
.stdin("fn main() {}")
20+
.stdin_buf(("fn main() {}").as_bytes())
2521
.input("-")
2622
.env("MAKEFLAGS", "--jobserver-auth=3,3")
2723
.set_aux_fd(3, std::fs::File::open("/dev/null").unwrap())

0 commit comments

Comments
 (0)