diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3065169e5e2cb..ea651c075d968 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2112,9 +2112,10 @@ impl Weak { /// assert!(empty.upgrade().is_none()); /// ``` #[stable(feature = "downgraded_weak", since = "1.10.0")] + #[rustc_const_unstable(feature = "const_weak_new", issue = "95091", reason = "recently added")] #[must_use] - pub fn new() -> Weak { - Weak { ptr: NonNull::new(usize::MAX as *mut RcBox).expect("MAX is not 0") } + pub const fn new() -> Weak { + Weak { ptr: unsafe { NonNull::new_unchecked(usize::MAX as *mut RcBox) } } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2140c3f168d1c..ba3187294e654 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1742,9 +1742,10 @@ impl Weak { /// assert!(empty.upgrade().is_none()); /// ``` #[stable(feature = "downgraded_weak", since = "1.10.0")] + #[rustc_const_unstable(feature = "const_weak_new", issue = "95091", reason = "recently added")] #[must_use] - pub fn new() -> Weak { - Weak { ptr: NonNull::new(usize::MAX as *mut ArcInner).expect("MAX is not 0") } + pub const fn new() -> Weak { + Weak { ptr: unsafe { NonNull::new_unchecked(usize::MAX as *mut ArcInner) } } } } diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 855f900430c4a..d95bc9b15c9c4 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -149,6 +149,11 @@ pub trait CommandExt: Sealed { fn arg0(&mut self, arg: S) -> &mut process::Command where S: AsRef; + + /// Sets the process group ID of the child process. Translates to a `setpgid` call in the child + /// process. + #[unstable(feature = "process_set_process_group", issue = "93857")] + fn process_group(&mut self, pgroup: i32) -> &mut process::Command; } #[stable(feature = "rust1", since = "1.0.0")] @@ -201,6 +206,11 @@ impl CommandExt for process::Command { self.as_inner_mut().set_arg_0(arg.as_ref()); self } + + fn process_group(&mut self, pgroup: i32) -> &mut process::Command { + self.as_inner_mut().pgroup(pgroup); + self + } } /// Unix-specific extensions to [`process::ExitStatus`] and diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index c8dc768d3fc8e..d1f59d2786e91 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1739,11 +1739,11 @@ fn test_windows_absolute() { let relative = r"a\b"; let mut expected = crate::env::current_dir().unwrap(); expected.push(relative); - assert_eq!(absolute(relative).unwrap(), expected); + assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str()); macro_rules! unchanged( ($path:expr) => { - assert_eq!(absolute($path).unwrap(), Path::new($path)); + assert_eq!(absolute($path).unwrap().as_os_str(), Path::new($path).as_os_str()); } ); @@ -1759,11 +1759,11 @@ fn test_windows_absolute() { // Verbatim paths are always unchanged, no matter what. unchanged!(r"\\?\path.\to/file.."); - assert_eq!(absolute(r"C:\path..\to.\file.").unwrap(), Path::new(r"C:\path..\to\file")); - assert_eq!(absolute(r"C:\path\to\COM1").unwrap(), Path::new(r"\\.\COM1")); - assert_eq!(absolute(r"C:\path\to\COM1.txt").unwrap(), Path::new(r"\\.\COM1")); - assert_eq!(absolute(r"C:\path\to\COM1 .txt").unwrap(), Path::new(r"\\.\COM1")); - assert_eq!(absolute(r"C:\path\to\cOnOuT$").unwrap(), Path::new(r"\\.\cOnOuT$")); + assert_eq!( + absolute(r"C:\path..\to.\file.").unwrap().as_os_str(), + Path::new(r"C:\path..\to\file").as_os_str() + ); + assert_eq!(absolute(r"COM1").unwrap().as_os_str(), Path::new(r"\\.\COM1").as_os_str()); } #[bench] diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 97985ddd3316b..27bee714f5b43 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -18,7 +18,7 @@ use crate::sys_common::IntoInner; #[cfg(not(target_os = "fuchsia"))] use crate::sys::fs::OpenOptions; -use libc::{c_char, c_int, gid_t, uid_t, EXIT_FAILURE, EXIT_SUCCESS}; +use libc::{c_char, c_int, gid_t, pid_t, uid_t, EXIT_FAILURE, EXIT_SUCCESS}; cfg_if::cfg_if! { if #[cfg(target_os = "fuchsia")] { @@ -82,6 +82,7 @@ pub struct Command { stderr: Option, #[cfg(target_os = "linux")] create_pidfd: bool, + pgroup: Option, } // Create a new type for argv, so that we can make it `Send` and `Sync` @@ -145,6 +146,7 @@ impl Command { stdin: None, stdout: None, stderr: None, + pgroup: None, } } @@ -167,6 +169,7 @@ impl Command { stdout: None, stderr: None, create_pidfd: false, + pgroup: None, } } @@ -202,6 +205,9 @@ impl Command { pub fn groups(&mut self, groups: &[gid_t]) { self.groups = Some(Box::from(groups)); } + pub fn pgroup(&mut self, pgroup: pid_t) { + self.pgroup = Some(pgroup); + } #[cfg(target_os = "linux")] pub fn create_pidfd(&mut self, val: bool) { @@ -265,6 +271,10 @@ impl Command { pub fn get_groups(&self) -> Option<&[gid_t]> { self.groups.as_deref() } + #[allow(dead_code)] + pub fn get_pgroup(&self) -> Option { + self.pgroup + } pub fn get_closures(&mut self) -> &mut Vec io::Result<()> + Send + Sync>> { &mut self.closures diff --git a/library/std/src/sys/unix/process/process_common/tests.rs b/library/std/src/sys/unix/process/process_common/tests.rs index 10aa34e9443b7..9f1a645372f42 100644 --- a/library/std/src/sys/unix/process/process_common/tests.rs +++ b/library/std/src/sys/unix/process/process_common/tests.rs @@ -67,3 +67,58 @@ fn test_process_mask() { t!(cat.wait()); } } + +#[test] +#[cfg_attr( + any( + // See test_process_mask + target_os = "macos", + target_arch = "arm", + target_arch = "aarch64", + target_arch = "riscv64", + ), + ignore +)] +fn test_process_group_posix_spawn() { + unsafe { + // Spawn a cat subprocess that's just going to hang since there is no I/O. + let mut cmd = Command::new(OsStr::new("cat")); + cmd.pgroup(0); + cmd.stdin(Stdio::MakePipe); + cmd.stdout(Stdio::MakePipe); + let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true)); + + // Check that we can kill its process group, which means there *is* one. + t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT))); + + t!(cat.wait()); + } +} + +#[test] +#[cfg_attr( + any( + // See test_process_mask + target_os = "macos", + target_arch = "arm", + target_arch = "aarch64", + target_arch = "riscv64", + ), + ignore +)] +fn test_process_group_no_posix_spawn() { + unsafe { + // Same as above, create hang-y cat. This time, force using the non-posix_spawnp path. + let mut cmd = Command::new(OsStr::new("cat")); + cmd.pgroup(0); + cmd.pre_exec(Box::new(|| Ok(()))); // pre_exec forces fork + exec + cmd.stdin(Stdio::MakePipe); + cmd.stdout(Stdio::MakePipe); + let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true)); + + // Check that we can kill its process group, which means there *is* one. + t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT))); + + t!(cat.wait()); + } +} diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 2a97a802a2036..3d305cd7310fd 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -320,6 +320,10 @@ impl Command { cvt(libc::chdir(cwd.as_ptr()))?; } + if let Some(pgroup) = self.get_pgroup() { + cvt(libc::setpgid(0, pgroup))?; + } + // emscripten has no signal support. #[cfg(not(target_os = "emscripten"))] { @@ -459,6 +463,8 @@ impl Command { None => None, }; + let pgroup = self.get_pgroup(); + // Safety: -1 indicates we don't have a pidfd. let mut p = unsafe { Process::new(0, -1) }; @@ -487,6 +493,8 @@ impl Command { cvt_nz(libc::posix_spawnattr_init(attrs.as_mut_ptr()))?; let attrs = PosixSpawnattr(&mut attrs); + let mut flags = 0; + let mut file_actions = MaybeUninit::uninit(); cvt_nz(libc::posix_spawn_file_actions_init(file_actions.as_mut_ptr()))?; let file_actions = PosixSpawnFileActions(&mut file_actions); @@ -516,13 +524,18 @@ impl Command { cvt_nz(f(file_actions.0.as_mut_ptr(), cwd.as_ptr()))?; } + if let Some(pgroup) = pgroup { + flags |= libc::POSIX_SPAWN_SETPGROUP; + cvt_nz(libc::posix_spawnattr_setpgroup(attrs.0.as_mut_ptr(), pgroup))?; + } + let mut set = MaybeUninit::::uninit(); cvt(sigemptyset(set.as_mut_ptr()))?; cvt_nz(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(), set.as_ptr()))?; cvt(sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?; cvt_nz(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(), set.as_ptr()))?; - let flags = libc::POSIX_SPAWN_SETSIGDEF | libc::POSIX_SPAWN_SETSIGMASK; + flags |= libc::POSIX_SPAWN_SETSIGDEF | libc::POSIX_SPAWN_SETSIGMASK; cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?; // Make sure we synchronize access to the global `environ` resource diff --git a/src/test/ui/check-cfg/mix.rs b/src/test/ui/check-cfg/mix.rs index 26c735c4a10bd..b51d356f61fdf 100644 --- a/src/test/ui/check-cfg/mix.rs +++ b/src/test/ui/check-cfg/mix.rs @@ -45,6 +45,28 @@ fn test_cfg_macro() { //~^ WARNING unexpected `cfg` condition name cfg!(any(feature = "bad", windows)); //~^ WARNING unexpected `cfg` condition value + cfg!(any(windows, xxx)); + //~^ WARNING unexpected `cfg` condition name + cfg!(all(unix, xxx)); + //~^ WARNING unexpected `cfg` condition name + cfg!(all(aa, bb)); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition name + cfg!(any(aa, bb)); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition name + cfg!(any(unix, feature = "zebra")); + //~^ WARNING unexpected `cfg` condition value + cfg!(any(xxx, feature = "zebra")); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition value + cfg!(any(xxx, unix, xxx)); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition name + cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + //~^ WARNING unexpected `cfg` condition value + //~| WARNING unexpected `cfg` condition value + //~| WARNING unexpected `cfg` condition value } fn main() {} diff --git a/src/test/ui/check-cfg/mix.stderr b/src/test/ui/check-cfg/mix.stderr index b273be774224d..08a338da104d0 100644 --- a/src/test/ui/check-cfg/mix.stderr +++ b/src/test/ui/check-cfg/mix.stderr @@ -62,5 +62,99 @@ LL | cfg!(any(feature = "bad", windows)); | = note: expected values for `feature` are: bar, foo -warning: 9 warnings emitted +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:48:23 + | +LL | cfg!(any(windows, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:50:20 + | +LL | cfg!(all(unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:52:14 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:52:18 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:55:14 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:55:18 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:58:20 + | +LL | cfg!(any(unix, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: bar, foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:60:14 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:60:19 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: bar, foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:63:14 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:63:25 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:66:14 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: bar, foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:66:33 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: bar, foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:66:52 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: bar, foo + +warning: 23 warnings emitted diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 3f2cd3ae232ba..503b624114a2a 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -487,11 +487,6 @@ fn configure_lldb(config: &Config) -> Option { return None; } - // Some older versions of LLDB seem to have problems with multiple - // instances running in parallel, so only run one test thread at a - // time. - env::set_var("RUST_TEST_THREADS", "1"); - Some(Config { debugger: Some(Debugger::Lldb), ..config.clone() }) }