Skip to content

Commit 1d0a40d

Browse files
committed
symlink the rustup-init binary during tests
We can't open it for writing as any concurrent forks would keep a writable file descriptor open which would prevent us from then executing the file with a "text file busy" error. On windows we keep copying as this problem isn't present and symlinks don't work that well on Windows.
1 parent fb08ece commit 1d0a40d

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

src/rustup-mock/src/clitools.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::env;
66
use std::process::Command;
77
use std::env::consts::EXE_SUFFIX;
88
use std::fs::{self, File};
9-
use std::io::{Read, Write};
9+
use std::io::{self, Read, Write};
1010
use std::sync::Mutex;
1111
use tempdir::TempDir;
1212
use {MockInstallerBuilder, MockCommand};
@@ -92,7 +92,22 @@ pub fn setup(s: Scenario, f: &Fn(&Config)) {
9292
let rustc_path = config.exedir.join(format!("rustc{}", EXE_SUFFIX));
9393
let cargo_path = config.exedir.join(format!("cargo{}", EXE_SUFFIX));
9494

95-
fs::copy(build_path, rustup_path).unwrap();
95+
// Don't copy an executable via `fs::copy` on Unix because that'll require
96+
// opening up the destination for writing. If one thread in our process then
97+
// forks the child will have the destination open as well (fd inheritance)
98+
// which will prevent us from then executing that binary.
99+
//
100+
// On Windows, however, handles aren't inherited across processes so we can
101+
// do fs::copy there, and on Unix we just do symlinks.
102+
#[cfg(windows)]
103+
fn copy_binary(src: &Path, dst: &Path) -> io::Result<()> {
104+
fs::copy(src, dst).map(|_| ())
105+
}
106+
#[cfg(unix)]
107+
fn copy_binary(src: &Path, dst: &Path) -> io::Result<()> {
108+
::std::os::unix::fs::symlink(src, dst)
109+
}
110+
copy_binary(&build_path, &rustup_path).unwrap();
96111
fs::hard_link(rustup_path, setup_path).unwrap();
97112
fs::hard_link(rustup_path, multirust_setup_path).unwrap();
98113
fs::hard_link(rustup_path, rustc_path).unwrap();

0 commit comments

Comments
 (0)