Skip to content

Commit 6f67fa0

Browse files
coolreader18Oneirical
authored andcommitted
Better comments for set_aux_fd
1 parent f6f9e10 commit 6f67fa0

File tree

4 files changed

+33
-18
lines changed

4 files changed

+33
-18
lines changed

Diff for: 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"

Diff for: src/tools/run-make-support/src/command.rs

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

154154
/// Set an auxiliary stream passed to the process, besides the stdio streams.
155+
///
156+
/// Use with caution - ideally, only set one aux fd; if there are multiple,
157+
/// their old `fd` may overlap with another's `newfd`, and thus will break.
158+
/// If you need more than 1 auxiliary file descriptor, rewrite this function
159+
/// to be able to support that.
155160
#[cfg(unix)]
156161
pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>(
157162
&mut self,
@@ -161,18 +166,28 @@ impl Command {
161166
use std::os::fd::AsRawFd;
162167
use std::os::unix::process::CommandExt;
163168

169+
let cvt = |x| if x == -1 { Err(std::io::Error::last_os_error()) } else { Ok(()) };
170+
164171
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-
});
172+
if fd.as_raw_fd() == newfd {
173+
// if fd is already where we want it, just turn off FD_CLOEXEC
174+
// SAFETY: io-safe: we have ownership over fd
175+
cvt(unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_SETFD, 0) })
176+
.expect("disabling CLOEXEC failed");
177+
// we still unconditionally set the pre_exec function, since it captures
178+
// `fd`, and we want to ensure that it stays open until the fork
175179
}
180+
let pre_exec = move || {
181+
if fd.as_raw_fd() != newfd {
182+
// set newfd to point to the same file as fd
183+
// SAFETY: io-"safe": newfd is. not necessarily an unused fd.
184+
// however, we're
185+
cvt(unsafe { libc::dup2(fd.as_raw_fd(), newfd) })?;
186+
}
187+
Ok(())
188+
};
189+
// SAFETY: dup2 is pre-exec-safe
190+
unsafe { self.cmd.pre_exec(pre_exec) };
176191
self
177192
}
178193

Diff for: 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,

Diff for: 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)