summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/unix
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /library/std/src/sys/unix
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/sys/unix')
-rw-r--r--library/std/src/sys/unix/args.rs16
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fs.rs20
-rw-r--r--library/std/src/sys/unix/mod.rs7
-rw-r--r--library/std/src/sys/unix/os.rs12
-rw-r--r--library/std/src/sys/unix/process/process_common.rs9
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs76
-rw-r--r--library/std/src/sys/unix/process/process_unix/tests.rs19
-rw-r--r--library/std/src/sys/unix/thread.rs3
-rw-r--r--library/std/src/sys/unix/thread_local_dtor.rs10
-rw-r--r--library/std/src/sys/unix/time.rs12
11 files changed, 136 insertions, 59 deletions
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index 2da17fabc..9f7dcc041 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -244,13 +244,15 @@ mod imp {
let mut res = Vec::new();
unsafe {
- let process_info_sel = sel_registerName("processInfo\0".as_ptr());
- let arguments_sel = sel_registerName("arguments\0".as_ptr());
- let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
- let count_sel = sel_registerName("count\0".as_ptr());
- let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());
-
- let klass = objc_getClass("NSProcessInfo\0".as_ptr());
+ let process_info_sel =
+ sel_registerName(c"processInfo".as_ptr() as *const libc::c_uchar);
+ let arguments_sel = sel_registerName(c"arguments".as_ptr() as *const libc::c_uchar);
+ let utf8_sel = sel_registerName(c"UTF8String".as_ptr() as *const libc::c_uchar);
+ let count_sel = sel_registerName(c"count".as_ptr() as *const libc::c_uchar);
+ let object_at_sel =
+ sel_registerName(c"objectAtIndex:".as_ptr() as *const libc::c_uchar);
+
+ let klass = objc_getClass(c"NSProcessInfo".as_ptr() as *const libc::c_uchar);
let info = objc_msgSend(klass, process_info_sel);
let args = objc_msgSend(info, arguments_sel);
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 3bb492fa9..3d4ba5098 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -174,17 +174,6 @@ pub mod os {
pub const EXE_EXTENSION: &str = "elf";
}
-#[cfg(all(target_os = "emscripten", target_arch = "asmjs"))]
-pub mod os {
- pub const FAMILY: &str = "unix";
- pub const OS: &str = "emscripten";
- pub const DLL_PREFIX: &str = "lib";
- pub const DLL_SUFFIX: &str = ".so";
- pub const DLL_EXTENSION: &str = "so";
- pub const EXE_SUFFIX: &str = ".js";
- pub const EXE_EXTENSION: &str = "js";
-}
-
#[cfg(all(target_os = "emscripten", target_arch = "wasm32"))]
pub mod os {
pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 40eb910fd..72e7b1b1f 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1140,7 +1140,7 @@ impl File {
cfg_has_statx! {
if let Some(ret) = unsafe { try_statx(
fd,
- b"\0" as *const _ as *const c_char,
+ c"".as_ptr() as *const c_char,
libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT,
libc::STATX_ALL,
) } {
@@ -1300,13 +1300,17 @@ impl File {
pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))]
- let to_timespec = |time: Option<SystemTime>| {
- match time {
- Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts),
- Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too large to set as a file time")),
- Some(_) => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too small to set as a file time")),
- None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }),
- }
+ let to_timespec = |time: Option<SystemTime>| match time {
+ Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts),
+ Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_io_error!(
+ io::ErrorKind::InvalidInput,
+ "timestamp is too large to set as a file time"
+ )),
+ Some(_) => Err(io::const_io_error!(
+ io::ErrorKind::InvalidInput,
+ "timestamp is too small to set as a file time"
+ )),
+ None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }),
};
cfg_if::cfg_if! {
if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] {
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 4b28f6feb..b5da5f870 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -1,6 +1,5 @@
#![allow(missing_docs, nonstandard_style)]
-use crate::ffi::CStr;
use crate::io::ErrorKind;
pub use self::rand::hashmap_random_keys;
@@ -75,7 +74,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// thread-id for the main thread and so renaming the main thread will rename the
// process and we only want to enable this on platforms we've tested.
if cfg!(target_os = "macos") {
- thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0"));
+ thread::Thread::set_name(&c"main");
}
unsafe fn sanitize_standard_fds() {
@@ -127,7 +126,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
if pfd.revents & libc::POLLNVAL == 0 {
continue;
}
- if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+ if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
// If the stream is closed but we failed to reopen it, abort the
// process. Otherwise we wouldn't preserve the safety of
// operations on the corresponding Rust object Stdin, Stdout, or
@@ -157,7 +156,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
use libc::open64;
for fd in 0..3 {
if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
- if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+ if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
// If the stream is closed but we failed to reopen it, abort the
// process. Otherwise we wouldn't preserve the safety of
// operations on the corresponding Rust object Stdin, Stdout, or
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index dc3c037c0..881b3a25c 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -180,7 +180,7 @@ pub fn getcwd() -> io::Result<PathBuf> {
}
#[cfg(target_os = "espidf")]
-pub fn chdir(p: &path::Path) -> io::Result<()> {
+pub fn chdir(_p: &path::Path) -> io::Result<()> {
super::unsupported::unsupported()
}
@@ -274,15 +274,19 @@ pub fn current_exe() -> io::Result<PathBuf> {
return path.canonicalize();
}
// Search PWD to infer current_exe.
- if let Some(pstr) = path.to_str() && pstr.contains("/") {
+ if let Some(pstr) = path.to_str()
+ && pstr.contains("/")
+ {
return getcwd().map(|cwd| cwd.join(path))?.canonicalize();
}
// Search PATH to infer current_exe.
if let Some(p) = getenv(OsStr::from_bytes("PATH".as_bytes())) {
for search_path in split_paths(&p) {
let pb = search_path.join(&path);
- if pb.is_file() && let Ok(metadata) = crate::fs::metadata(&pb) &&
- metadata.permissions().mode() & 0o111 != 0 {
+ if pb.is_file()
+ && let Ok(metadata) = crate::fs::metadata(&pb)
+ && metadata.permissions().mode() & 0o111 != 0
+ {
return pb.canonicalize();
}
}
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index bac32d9e6..c5f04fb8b 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -24,11 +24,11 @@ cfg_if::cfg_if! {
if #[cfg(target_os = "fuchsia")] {
// fuchsia doesn't have /dev/null
} else if #[cfg(target_os = "redox")] {
- const DEV_NULL: &str = "null:\0";
+ const DEV_NULL: &CStr = c"null:";
} else if #[cfg(target_os = "vxworks")] {
- const DEV_NULL: &str = "/null\0";
+ const DEV_NULL: &CStr = c"/null";
} else {
- const DEV_NULL: &str = "/dev/null\0";
+ const DEV_NULL: &CStr = c"/dev/null";
}
}
@@ -481,8 +481,7 @@ impl Stdio {
let mut opts = OpenOptions::new();
opts.read(readable);
opts.write(!readable);
- let path = unsafe { CStr::from_ptr(DEV_NULL.as_ptr() as *const _) };
- let fd = File::open_c(&path, &opts)?;
+ let fd = File::open_c(DEV_NULL, &opts)?;
Ok((ChildStdio::Owned(fd.into_inner()), None))
}
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 72aca4e66..ee86a5f88 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -9,6 +9,8 @@ use core::ffi::NonZero_c_int;
#[cfg(target_os = "linux")]
use crate::os::linux::process::PidFd;
+#[cfg(target_os = "linux")]
+use crate::os::unix::io::AsRawFd;
#[cfg(any(
target_os = "macos",
@@ -696,11 +698,12 @@ impl Command {
msg.msg_iov = &mut iov as *mut _ as *mut _;
msg.msg_iovlen = 1;
- msg.msg_controllen = mem::size_of_val(&cmsg.buf) as _;
- msg.msg_control = &mut cmsg.buf as *mut _ as *mut _;
// only attach cmsg if we successfully acquired the pidfd
if pidfd >= 0 {
+ msg.msg_controllen = mem::size_of_val(&cmsg.buf) as _;
+ msg.msg_control = &mut cmsg.buf as *mut _ as *mut _;
+
let hdr = CMSG_FIRSTHDR(&mut msg as *mut _ as *mut _);
(*hdr).cmsg_level = SOL_SOCKET;
(*hdr).cmsg_type = SCM_RIGHTS;
@@ -717,7 +720,7 @@ impl Command {
// so we get a consistent SEQPACKET order
match cvt_r(|| libc::sendmsg(sock.as_raw(), &msg, 0)) {
Ok(0) => {}
- _ => rtabort!("failed to communicate with parent process"),
+ other => rtabort!("failed to communicate with parent process. {:?}", other),
}
}
}
@@ -748,7 +751,7 @@ impl Command {
msg.msg_controllen = mem::size_of::<Cmsg>() as _;
msg.msg_control = &mut cmsg as *mut _ as *mut _;
- match cvt_r(|| libc::recvmsg(sock.as_raw(), &mut msg, 0)) {
+ match cvt_r(|| libc::recvmsg(sock.as_raw(), &mut msg, libc::MSG_CMSG_CLOEXEC)) {
Err(_) => return -1,
Ok(_) => {}
}
@@ -787,7 +790,7 @@ pub struct Process {
// On Linux, stores the pidfd created for this child.
// This is None if the user did not request pidfd creation,
// or if the pidfd could not be created for some reason
- // (e.g. the `clone3` syscall was not available).
+ // (e.g. the `pidfd_open` syscall was not available).
#[cfg(target_os = "linux")]
pidfd: Option<PidFd>,
}
@@ -816,10 +819,23 @@ impl Process {
// and used for another process, and we probably shouldn't be killing
// random processes, so return Ok because the process has exited already.
if self.status.is_some() {
- Ok(())
- } else {
- cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
+ return Ok(());
+ }
+ #[cfg(target_os = "linux")]
+ if let Some(pid_fd) = self.pidfd.as_ref() {
+ // pidfd_send_signal predates pidfd_open. so if we were able to get an fd then sending signals will work too
+ return cvt(unsafe {
+ libc::syscall(
+ libc::SYS_pidfd_send_signal,
+ pid_fd.as_raw_fd(),
+ libc::SIGKILL,
+ crate::ptr::null::<()>(),
+ 0,
+ )
+ })
+ .map(drop);
}
+ cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
}
pub fn wait(&mut self) -> io::Result<ExitStatus> {
@@ -827,6 +843,17 @@ impl Process {
if let Some(status) = self.status {
return Ok(status);
}
+ #[cfg(target_os = "linux")]
+ if let Some(pid_fd) = self.pidfd.as_ref() {
+ let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() };
+
+ cvt_r(|| unsafe {
+ libc::waitid(libc::P_PIDFD, pid_fd.as_raw_fd() as u32, &mut siginfo, libc::WEXITED)
+ })?;
+ let status = ExitStatus::from_waitid_siginfo(siginfo);
+ self.status = Some(status);
+ return Ok(status);
+ }
let mut status = 0 as c_int;
cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
self.status = Some(ExitStatus::new(status));
@@ -837,6 +864,25 @@ impl Process {
if let Some(status) = self.status {
return Ok(Some(status));
}
+ #[cfg(target_os = "linux")]
+ if let Some(pid_fd) = self.pidfd.as_ref() {
+ let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() };
+
+ cvt(unsafe {
+ libc::waitid(
+ libc::P_PIDFD,
+ pid_fd.as_raw_fd() as u32,
+ &mut siginfo,
+ libc::WEXITED | libc::WNOHANG,
+ )
+ })?;
+ if unsafe { siginfo.si_pid() } == 0 {
+ return Ok(None);
+ }
+ let status = ExitStatus::from_waitid_siginfo(siginfo);
+ self.status = Some(status);
+ return Ok(Some(status));
+ }
let mut status = 0 as c_int;
let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?;
if pid == 0 {
@@ -866,6 +912,20 @@ impl ExitStatus {
ExitStatus(status)
}
+ #[cfg(target_os = "linux")]
+ pub fn from_waitid_siginfo(siginfo: libc::siginfo_t) -> ExitStatus {
+ let status = unsafe { siginfo.si_status() };
+
+ match siginfo.si_code {
+ libc::CLD_EXITED => ExitStatus((status & 0xff) << 8),
+ libc::CLD_KILLED => ExitStatus(status),
+ libc::CLD_DUMPED => ExitStatus(status | 0x80),
+ libc::CLD_CONTINUED => ExitStatus(0xffff),
+ libc::CLD_STOPPED | libc::CLD_TRAPPED => ExitStatus(((status & 0xff) << 8) | 0x7f),
+ _ => unreachable!("waitid() should only return the above codes"),
+ }
+ }
+
fn exited(&self) -> bool {
libc::WIFEXITED(self.0)
}
diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs
index 6aa79e7f9..6e952ed7c 100644
--- a/library/std/src/sys/unix/process/process_unix/tests.rs
+++ b/library/std/src/sys/unix/process/process_unix/tests.rs
@@ -64,7 +64,8 @@ fn test_command_fork_no_unwind() {
#[test]
#[cfg(target_os = "linux")]
fn test_command_pidfd() {
- use crate::os::fd::RawFd;
+ use crate::assert_matches::assert_matches;
+ use crate::os::fd::{AsRawFd, RawFd};
use crate::os::linux::process::{ChildExt, CommandExt};
use crate::process::Command;
@@ -78,10 +79,22 @@ fn test_command_pidfd() {
};
// always exercise creation attempts
- let child = Command::new("echo").create_pidfd(true).spawn().unwrap();
+ let mut child = Command::new("false").create_pidfd(true).spawn().unwrap();
// but only check if we know that the kernel supports pidfds
if pidfd_open_available {
- assert!(child.pidfd().is_ok())
+ assert!(child.pidfd().is_ok());
}
+ if let Ok(pidfd) = child.pidfd() {
+ let flags = super::cvt(unsafe { libc::fcntl(pidfd.as_raw_fd(), libc::F_GETFD) }).unwrap();
+ assert!(flags & libc::FD_CLOEXEC != 0);
+ }
+ let status = child.wait().expect("error waiting on pidfd");
+ assert_eq!(status.code(), Some(1));
+
+ let mut child = Command::new("sleep").arg("1000").create_pidfd(true).spawn().unwrap();
+ assert_matches!(child.try_wait(), Ok(None));
+ child.kill().expect("failed to kill child");
+ let status = child.wait().expect("error waiting on pidfd");
+ assert_eq!(status.signal(), Some(libc::SIGKILL));
}
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 29db9468e..76b96bb37 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -163,10 +163,9 @@ impl Thread {
#[cfg(target_os = "netbsd")]
pub fn set_name(name: &CStr) {
unsafe {
- let cname = CStr::from_bytes_with_nul_unchecked(b"%s\0".as_slice());
let res = libc::pthread_setname_np(
libc::pthread_self(),
- cname.as_ptr(),
+ c"%s".as_ptr(),
name.as_ptr() as *mut libc::c_void,
);
debug_assert_eq!(res, 0);
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index 06399e8a2..ac85531c3 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -12,7 +12,13 @@
// compiling from a newer linux to an older linux, so we also have a
// fallback implementation to use as well.
#[allow(unexpected_cfgs)]
-#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox", target_os = "hurd"))]
+#[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "redox",
+ target_os = "hurd"
+))]
// FIXME: The Rust compiler currently omits weakly function definitions (i.e.,
// __cxa_thread_atexit_impl) and its metadata from LLVM IR.
#[no_sanitize(cfi, kcfi)]
@@ -23,6 +29,8 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
/// This is necessary because the __cxa_thread_atexit_impl implementation
/// std links to by default may be a C or C++ implementation that was not
/// compiled using the Clang integer normalization option.
+ #[cfg(sanitizer_cfi_normalize_integers)]
+ use core::ffi::c_int;
#[cfg(not(sanitizer_cfi_normalize_integers))]
#[cfi_encoding = "i"]
#[repr(transparent)]
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index f2e86a4fb..f62eb828e 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -23,11 +23,11 @@ struct Nanoseconds(u32);
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SystemTime {
- pub(in crate::sys::unix) t: Timespec,
+ pub(crate) t: Timespec,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub(in crate::sys::unix) struct Timespec {
+pub(crate) struct Timespec {
tv_sec: i64,
tv_nsec: Nanoseconds,
}
@@ -239,11 +239,11 @@ impl From<libc::timespec> for Timespec {
not(target_arch = "riscv32")
))]
#[repr(C)]
-pub(in crate::sys::unix) struct __timespec64 {
- pub(in crate::sys::unix) tv_sec: i64,
+pub(crate) struct __timespec64 {
+ pub(crate) tv_sec: i64,
#[cfg(target_endian = "big")]
_padding: i32,
- pub(in crate::sys::unix) tv_nsec: i32,
+ pub(crate) tv_nsec: i32,
#[cfg(target_endian = "little")]
_padding: i32,
}
@@ -255,7 +255,7 @@ pub(in crate::sys::unix) struct __timespec64 {
not(target_arch = "riscv32")
))]
impl __timespec64 {
- pub(in crate::sys::unix) fn new(tv_sec: i64, tv_nsec: i32) -> Self {
+ pub(crate) fn new(tv_sec: i64, tv_nsec: i32) -> Self {
Self { tv_sec, tv_nsec, _padding: 0 }
}
}