diff --git a/crates/host_env/src/errno_wasm.rs b/crates/host_env/src/errno_wasm.rs index 1bf4922c1..a5103ef04 100644 --- a/crates/host_env/src/errno_wasm.rs +++ b/crates/host_env/src/errno_wasm.rs @@ -1,10 +1,86 @@ //! Errno numbers for `wasm32-unknown-unknown`. //! -//! There is no libc errno table. The values are the Linux ABI the stdlib -//! and `OSError` subclasses match against. +//! There is no libc errno table. The values are the Darwin/BSD numbers the +//! guest `O_*` flags and `OSError` subclasses match against. + +#[must_use] +pub fn strerror_string(errno: i32) -> Option { + errors::strerror(errno).map(str::to_owned) +} pub mod errors { - pub const EAGAIN: i32 = 11; - pub const ECONNABORTED: i32 = 103; - pub const ECONNRESET: i32 = 104; + pub const EPERM: i32 = 1; + pub const ENOENT: i32 = 2; + pub const ESRCH: i32 = 3; + pub const EINTR: i32 = 4; + pub const EIO: i32 = 5; + pub const EBADF: i32 = 9; + pub const ECHILD: i32 = 10; + pub const EAGAIN: i32 = 35; + pub const EWOULDBLOCK: i32 = 35; + pub const EINPROGRESS: i32 = 36; + pub const EALREADY: i32 = 37; + pub const EPIPE: i32 = 32; + pub const ENOTDIR: i32 = 20; + pub const EISDIR: i32 = 21; + pub const EINVAL: i32 = 22; + pub const EMFILE: i32 = 24; + pub const ESPIPE: i32 = 29; + pub const EROFS: i32 = 30; + pub const EACCES: i32 = 13; + pub const EEXIST: i32 = 17; + pub const ENOTSUP: i32 = 45; + pub const EAFNOSUPPORT: i32 = 47; + pub const ECONNABORTED: i32 = 53; + pub const ECONNRESET: i32 = 54; + pub const ESHUTDOWN: i32 = 58; + pub const ETIMEDOUT: i32 = 60; + pub const ECONNREFUSED: i32 = 61; + + pub fn strerror(errno: i32) -> Option<&'static str> { + Some(match errno { + EPERM => "Operation not permitted", + ENOENT => "No such file or directory", + ESRCH => "No such process", + EIO => "Input/output error", + EINTR => "Interrupted system call", + ECHILD => "No child processes", + EACCES => "Permission denied", + EEXIST => "File exists", + ENOTDIR => "Not a directory", + EISDIR => "Is a directory", + EPIPE => "Broken pipe", + EAGAIN => "Resource temporarily unavailable", + EINPROGRESS => "Operation now in progress", + EALREADY => "Operation already in progress", + ENOTSUP => "Operation not supported", + EAFNOSUPPORT => "Address family not supported by protocol", + ECONNABORTED => "Software caused connection abort", + ECONNRESET => "Connection reset by peer", + ETIMEDOUT => "Operation timed out", + ECONNREFUSED => "Connection refused", + EBADF => "Bad file descriptor", + EINVAL => "Invalid argument", + EMFILE => "Too many open files", + ESPIPE => "Illegal seek", + EROFS => "Read-only file system", + ESHUTDOWN => "Can't send after socket shutdown", + _ => return None, + }) + } +} + +#[cfg(test)] +mod tests { + use super::errors; + + #[test] + fn eagain_is_darwin() { + assert_eq!(errors::EAGAIN, 35); + assert_eq!(errors::EWOULDBLOCK, 35); + assert_eq!( + errors::strerror(errors::EAGAIN), + Some("Resource temporarily unavailable") + ); + } } diff --git a/crates/host_env/src/fcntl.rs b/crates/host_env/src/fcntl.rs index ee0cd58f2..1839d344d 100644 --- a/crates/host_env/src/fcntl.rs +++ b/crates/host_env/src/fcntl.rs @@ -7,6 +7,17 @@ use crate::os::CheckLibcResult; pub use libc::{F_GETFD, F_GETFL, F_SETFD, F_SETFL, FD_CLOEXEC}; +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox" +))] +pub use libc::{F_LOCK, F_TEST, F_TLOCK, F_ULOCK}; + #[cfg(not(target_os = "wasi"))] pub use libc::{F_DUPFD, F_DUPFD_CLOEXEC, F_GETLK, F_SETLK, F_SETLKW}; diff --git a/crates/host_env/src/fileutils.rs b/crates/host_env/src/fileutils.rs index affb6d220..8db9af895 100644 --- a/crates/host_env/src/fileutils.rs +++ b/crates/host_env/src/fileutils.rs @@ -466,7 +466,7 @@ pub fn fopen(path: &std::path::Path, mode: &str) -> std::io::Result<*mut CFile> // Convert File handle to CRT file descriptor let handle = file.into_raw_handle(); - let fd = unsafe { libc::open_osfhandle(handle as isize, libc::O_RDONLY) }; + let fd = unsafe { libc::open_osfhandle(handle as isize, crate::os::O_RDONLY) }; if fd == -1 { return Err(std::io::Error::last_os_error()); } diff --git a/crates/host_env/src/io.rs b/crates/host_env/src/io.rs index f32ef2f69..1b205c252 100644 --- a/crates/host_env/src/io.rs +++ b/crates/host_env/src/io.rs @@ -82,7 +82,7 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result { if rwa { @@ -97,7 +97,7 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result { if rwa { @@ -105,7 +105,7 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result { if plus { @@ -124,20 +124,20 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result) { - unsafe { suppress_iph!(_setmode(fd, libc::O_BINARY)) }; + unsafe { suppress_iph!(_setmode(fd, crate::os::O_BINARY)) }; } #[must_use] diff --git a/crates/host_env/src/multiprocessing.rs b/crates/host_env/src/multiprocessing.rs index 6da997f14..b62cc0a0e 100644 --- a/crates/host_env/src/multiprocessing.rs +++ b/crates/host_env/src/multiprocessing.rs @@ -136,8 +136,14 @@ impl SemHandle { unlink: bool, ) -> Result<(Self, Option), SemError> { let cname = semaphore_name(name)?; - let raw = - unsafe { libc::sem_open(cname.as_ptr(), libc::O_CREAT | libc::O_EXCL, 0o600, value) }; + let raw = unsafe { + libc::sem_open( + cname.as_ptr(), + crate::os::O_CREAT | crate::os::O_EXCL, + 0o600, + value, + ) + }; if raw == libc::SEM_FAILED { return Err(SemError::from_errno(Errno::last())); } diff --git a/crates/host_env/src/nt.rs b/crates/host_env/src/nt.rs index 47745ba44..9f1c1c23d 100644 --- a/crates/host_env/src/nt.rs +++ b/crates/host_env/src/nt.rs @@ -1369,7 +1369,7 @@ pub fn pipe() -> io::Result<(i32, i32)> { let write_fd = match crate::msvcrt::open_osfhandle( write_handle.as_raw_handle() as isize, - libc::O_WRONLY | O_NOINHERIT, + crate::os::O_WRONLY | O_NOINHERIT, ) { Ok(fd) => { let _ = write_handle.into_raw_handle(); @@ -2370,9 +2370,9 @@ pub fn open_console_path_fd(path: &widestring::WideCStr, writable: bool) -> io:: } let osf_flags = if writable { - libc::O_WRONLY | libc::O_BINARY | 0x80 + crate::os::O_WRONLY | crate::os::O_BINARY | 0x80 } else { - libc::O_RDONLY | libc::O_BINARY | 0x80 + crate::os::O_RDONLY | crate::os::O_BINARY | 0x80 }; match crate::msvcrt::open_osfhandle(handle as isize, osf_flags) { Ok(fd) => Ok(fd), diff --git a/crates/host_env/src/os.rs b/crates/host_env/src/os.rs index ae3784ace..e37dd1d0c 100644 --- a/crates/host_env/src/os.rs +++ b/crates/host_env/src/os.rs @@ -40,6 +40,124 @@ pub use libc::AT_FDCWD; #[cfg(not(any(unix, target_os = "wasi")))] pub const AT_FDCWD: i32 = -100; +#[cfg(unix)] +pub use libc::{AT_REMOVEDIR, AT_SYMLINK_FOLLOW, AT_SYMLINK_NOFOLLOW}; + +#[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple" +))] +pub use libc::AT_EACCESS; + +/// bionic does not export `AT_EACCESS`; the value is the Linux `fcntl.h` one. +#[cfg(target_os = "android")] +pub const AT_EACCESS: i32 = 0x200; + +#[cfg(all(unix, not(target_os = "redox")))] +pub use libc::{ST_NOSUID, ST_RDONLY}; + +/// `open(2)` flags. libc on hosts that bind them; Darwin/BSD numbers on +/// `wasm32-unknown-unknown`, matching the guest errno table. +#[cfg(any(unix, windows, target_os = "wasi"))] +pub use libc::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}; + +#[cfg(unix)] +pub use libc::{O_ACCMODE, O_CLOEXEC, O_DIRECTORY, O_NOFOLLOW, O_NONBLOCK}; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox" +))] +pub use libc::{O_ASYNC, O_NDELAY, O_NOCTTY}; + +#[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd" +))] +pub use libc::O_DSYNC; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd" +))] +pub use libc::O_SYNC; + +#[cfg(any( + target_os = "dragonfly", + target_os = "freebsd", + target_os = "macos", + target_os = "netbsd", + target_os = "redox" +))] +pub use libc::O_FSYNC; + +#[cfg(any(target_os = "linux", target_os = "android"))] +pub use libc::{O_DIRECT, O_LARGEFILE, O_NOATIME, O_PATH, O_RSYNC, O_TMPFILE}; + +#[cfg(target_os = "freebsd")] +pub use libc::{O_DIRECT, O_PATH}; + +#[cfg(target_os = "redox")] +pub use libc::O_PATH; + +#[cfg(target_os = "netbsd")] +pub use libc::{O_DIRECT, O_RSYNC}; + +#[cfg(target_os = "dragonfly")] +pub use libc::O_DIRECT; + +#[cfg(any(target_os = "macos", target_os = "ios"))] +pub use libc::{O_EVTONLY, O_EXEC, O_EXLOCK, O_NOFOLLOW_ANY, O_SEARCH, O_SHLOCK, O_SYMLINK}; + +#[cfg(any( + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "redox" +))] +pub use libc::{O_EXLOCK, O_SHLOCK}; + +#[cfg(target_os = "redox")] +pub use libc::O_SYMLINK; + +#[cfg(windows)] +pub use libc::{O_BINARY, O_NOINHERIT, O_RANDOM, O_SEQUENTIAL, O_TEMPORARY, O_TEXT}; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +mod wasm_oflag { + pub const O_RDONLY: i32 = 0x0000; + pub const O_WRONLY: i32 = 0x0001; + pub const O_RDWR: i32 = 0x0002; + pub const O_ACCMODE: i32 = 0x0003; + pub const O_NONBLOCK: i32 = 0x0004; + pub const O_APPEND: i32 = 0x0008; + pub const O_SYNC: i32 = 0x0080; + pub const O_NOFOLLOW: i32 = 0x0100; + pub const O_CREAT: i32 = 0x0200; + pub const O_TRUNC: i32 = 0x0400; + pub const O_EXCL: i32 = 0x0800; + pub const O_DIRECTORY: i32 = 0x0010_0000; + pub const O_CLOEXEC: i32 = 0x0100_0000; + pub const O_NDELAY: i32 = O_NONBLOCK; +} + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +pub use wasm_oflag::*; + /// BSD `chflags` bits the `libc` crate does not bind. Published by `_stat` /// on every platform. pub const UF_SETTABLE: u32 = 0x0000ffff; @@ -837,3 +955,16 @@ pub fn winerror_to_errno(winerror: i32) -> i32 { _ => EINVAL, } } + +#[cfg(test)] +mod tests { + #[test] + fn o_rdonly_is_zero() { + assert_eq!(super::O_RDONLY, 0); + } + + #[test] + fn o_wronly_is_one() { + assert_eq!(super::O_WRONLY, 1); + } +} diff --git a/crates/host_env/src/posix.rs b/crates/host_env/src/posix.rs index 4eb52aa68..e456c8c23 100644 --- a/crates/host_env/src/posix.rs +++ b/crates/host_env/src/posix.rs @@ -33,6 +33,145 @@ pub const EX_PROTOCOL: i32 = 76; pub const EX_NOPERM: i32 = 77; pub const EX_CONFIG: i32 = 78; +/// Remaining `posix` integer names the VM still took from `libc`. +#[cfg(any(target_os = "android", target_os = "redox", unix))] +pub use libc::{PRIO_PGRP, PRIO_PROCESS, PRIO_USER}; + +#[cfg(target_os = "macos")] +pub use libc::{ + COPYFILE_ACL, COPYFILE_DATA, COPYFILE_STAT, COPYFILE_XATTR, PRIO_DARWIN_BG, PRIO_DARWIN_NONUI, + PRIO_DARWIN_PROCESS, PRIO_DARWIN_THREAD, TMP_MAX, +}; + +#[cfg(target_os = "linux")] +pub use libc::PIDFD_NONBLOCK; + +#[cfg(any(target_os = "android", target_os = "linux"))] +pub use libc::{ + CLONE_FILES, CLONE_FS, CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, + CLONE_NEWUSER, CLONE_NEWUTS, CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, CLONE_VM, + MFD_HUGE_SHIFT, P_PIDFD, SCHED_BATCH, SCHED_DEADLINE, SCHED_IDLE, SCHED_NORMAL, + SCHED_RESET_ON_FORK, SPLICE_F_MORE, SPLICE_F_MOVE, SPLICE_F_NONBLOCK, +}; + +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "netbsd"))] +pub use libc::{XATTR_CREATE, XATTR_REPLACE}; + +#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +pub use libc::{ + MFD_ALLOW_SEALING, MFD_CLOEXEC, MFD_HUGE_MASK, MFD_HUGETLB, POSIX_FADV_DONTNEED, + POSIX_FADV_NOREUSE, POSIX_FADV_NORMAL, POSIX_FADV_RANDOM, POSIX_FADV_SEQUENTIAL, + POSIX_FADV_WILLNEED, +}; + +#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox", unix))] +pub use libc::{RTLD_LAZY, RTLD_NOW, WNOHANG}; + +#[cfg(any(target_os = "android", target_os = "macos", target_os = "redox", unix))] +pub use libc::RTLD_GLOBAL; + +#[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd" +))] +pub use libc::{ + EFD_CLOEXEC, EFD_NONBLOCK, EFD_SEMAPHORE, TFD_CLOEXEC, TFD_NONBLOCK, TFD_TIMER_ABSTIME, + TFD_TIMER_CANCEL_ON_SET, +}; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "linux", + target_os = "netbsd" +))] +pub use libc::{GRND_NONBLOCK, GRND_RANDOM}; + +#[cfg(any( + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd" +))] +pub use libc::SCHED_OTHER; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos" +))] +pub use libc::{RTLD_NODELETE, SEEK_DATA, SEEK_HOLE}; + +#[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox", + unix +))] +pub use libc::RTLD_LOCAL; + +#[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_os = "redox", + unix +))] +pub use libc::WUNTRACED; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd" +))] +pub use libc::{ + CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, CLD_TRAPPED, P_ALL, P_PGID, + P_PID, SCHED_FIFO, SCHED_RR, +}; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox" +))] +pub use libc::{RTLD_NOLOAD, WEXITED, WNOWAIT, WSTOPPED}; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox", + unix +))] +pub use libc::WCONTINUED; + +#[cfg(all(target_os = "linux", target_env = "gnu"))] +pub use libc::RTLD_DEEPBIND; + +#[cfg(unix)] +pub use libc::{UTIME_NOW, UTIME_OMIT}; + +#[cfg(target_os = "freebsd")] +pub use libc::{SF_MNOWAIT, SF_NOCACHE, SF_NODISKIO, SF_SYNC}; + pub struct UnameInfo { pub sysname: String, pub nodename: String, diff --git a/crates/vm/src/signal.rs b/crates/vm/src/signal.rs index 5395580b0..fa9cc599a 100644 --- a/crates/vm/src/signal.rs +++ b/crates/vm/src/signal.rs @@ -182,6 +182,11 @@ mod mt { EVAL_BREAKER.fetch_and(!STOP_BIT, Ordering::Release); } + #[cfg(test)] + pub(crate) fn stop_bit_set() -> bool { + EVAL_BREAKER.load(Ordering::Relaxed) & STOP_BIT != 0 + } + /// Record that finalization has begun. See `FINALIZING_BIT`. pub(crate) fn set_finalizing_bit() { EVAL_BREAKER.fetch_or(FINALIZING_BIT, Ordering::Release); @@ -198,6 +203,8 @@ mod mt { } } +#[cfg(all(test, feature = "threading"))] +pub(crate) use mt::stop_bit_set; #[cfg(feature = "threading")] pub(crate) use mt::{ clear_qsbr_bit, clear_stop_bit, qsbr_bit_set, schedule_gc, set_finalizing_bit, set_qsbr_bit, diff --git a/crates/vm/src/stdlib/nt.rs b/crates/vm/src/stdlib/nt.rs index 90c5ff031..19cb6e5b5 100644 --- a/crates/vm/src/stdlib/nt.rs +++ b/crates/vm/src/stdlib/nt.rs @@ -25,7 +25,9 @@ pub(crate) mod module { use std::os::windows::io::AsRawHandle; #[pyattr] - use libc::{O_BINARY, O_NOINHERIT, O_RANDOM, O_SEQUENTIAL, O_TEMPORARY, O_TEXT}; + use rustpython_host_env::os::{ + O_BINARY, O_NOINHERIT, O_RANDOM, O_SEQUENTIAL, O_TEMPORARY, O_TEXT, + }; #[pyattr] use host_msvcrt::{ diff --git a/crates/vm/src/stdlib/os.rs b/crates/vm/src/stdlib/os.rs index 00bf7b979..9862a1afd 100644 --- a/crates/vm/src/stdlib/os.rs +++ b/crates/vm/src/stdlib/os.rs @@ -242,7 +242,7 @@ pub(super) mod _os { const SCANDIR_FD: bool = cfg!(all(unix, not(target_os = "redox"))); #[pyattr] - use libc::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}; + use crate::host_env::os::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}; #[pyattr] pub(crate) use crate::host_env::os::{F_OK, R_OK, W_OK, X_OK}; @@ -250,11 +250,7 @@ pub(super) mod _os { // ST_RDONLY and ST_NOSUID flags for statvfs #[cfg(all(unix, not(target_os = "redox")))] #[pyattr] - const ST_RDONLY: libc::c_ulong = libc::ST_RDONLY; - - #[cfg(all(unix, not(target_os = "redox")))] - #[pyattr] - const ST_NOSUID: libc::c_ulong = libc::ST_NOSUID; + use crate::host_env::os::{ST_NOSUID, ST_RDONLY}; #[pyfunction] fn close(fd: crt_fd::Owned) -> io::Result<()> { @@ -299,14 +295,14 @@ pub(super) mod _os { let fd = { let [] = dir_fd.0; let name = name.to_wide_cstring(vm)?; - let flags = flags | libc::O_NOINHERIT; + let flags = flags | crate::host_env::os::O_NOINHERIT; crt_fd::wopen(&name, flags, mode) }; #[cfg(not(windows))] let fd = { let name = name.clone().into_cstring(vm)?; #[cfg(not(target_os = "wasi"))] - let flags = flags | libc::O_CLOEXEC; + let flags = flags | crate::host_env::os::O_CLOEXEC; #[cfg(not(target_os = "redox"))] if let Some(dir_fd) = dir_fd.get_opt() { crt_fd::openat(dir_fd, &name, flags, mode) diff --git a/crates/vm/src/stdlib/posix.rs b/crates/vm/src/stdlib/posix.rs index 4076523c8..f5760d773 100644 --- a/crates/vm/src/stdlib/posix.rs +++ b/crates/vm/src/stdlib/posix.rs @@ -48,48 +48,59 @@ pub mod module { #[cfg(target_os = "linux")] #[pyattr] - use libc::PIDFD_NONBLOCK; + use rustpython_host_env::posix::PIDFD_NONBLOCK; #[cfg(target_os = "macos")] #[pyattr] - use libc::{ - COPYFILE_DATA as _COPYFILE_DATA, O_EVTONLY, O_NOFOLLOW_ANY, PRIO_DARWIN_BG, - PRIO_DARWIN_NONUI, PRIO_DARWIN_PROCESS, PRIO_DARWIN_THREAD, + use rustpython_host_env::posix::{ + COPYFILE_DATA as _COPYFILE_DATA, PRIO_DARWIN_BG, PRIO_DARWIN_NONUI, PRIO_DARWIN_PROCESS, + PRIO_DARWIN_THREAD, }; + #[cfg(target_os = "macos")] + #[pyattr] + use rustpython_host_env::os::{O_EVTONLY, O_NOFOLLOW_ANY}; + #[cfg(target_os = "freebsd")] #[pyattr] - use libc::{SF_MNOWAIT, SF_NOCACHE, SF_NODISKIO, SF_SYNC}; + use rustpython_host_env::posix::{SF_MNOWAIT, SF_NOCACHE, SF_NODISKIO, SF_SYNC}; #[cfg(any(target_os = "android", target_os = "linux"))] #[pyattr] - use libc::{ + use rustpython_host_env::posix::{ CLONE_FILES, CLONE_FS, CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUSER, CLONE_NEWUTS, CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, - CLONE_VM, MFD_HUGE_SHIFT, O_NOATIME, O_TMPFILE, P_PIDFD, SCHED_BATCH, SCHED_DEADLINE, - SCHED_IDLE, SCHED_NORMAL, SCHED_RESET_ON_FORK, SPLICE_F_MORE, SPLICE_F_MOVE, - SPLICE_F_NONBLOCK, + CLONE_VM, MFD_HUGE_SHIFT, P_PIDFD, SCHED_BATCH, SCHED_DEADLINE, SCHED_IDLE, SCHED_NORMAL, + SCHED_RESET_ON_FORK, SPLICE_F_MORE, SPLICE_F_MOVE, SPLICE_F_NONBLOCK, }; + #[cfg(any(target_os = "android", target_os = "linux"))] + #[pyattr] + use rustpython_host_env::os::{O_NOATIME, O_TMPFILE}; + #[cfg(any(target_os = "macos", target_os = "redox"))] #[pyattr] - use libc::O_SYMLINK; + use rustpython_host_env::os::O_SYMLINK; #[cfg(any(target_os = "android", target_os = "redox", unix))] #[pyattr] - use libc::{O_NOFOLLOW, PRIO_PGRP, PRIO_PROCESS, PRIO_USER}; + use rustpython_host_env::posix::{PRIO_PGRP, PRIO_PROCESS, PRIO_USER}; + + #[cfg(any(target_os = "android", target_os = "redox", unix))] + #[pyattr] + use rustpython_host_env::os::O_NOFOLLOW; #[cfg(any(target_os = "linux", target_os = "macos", target_os = "netbsd"))] #[pyattr] - use libc::{XATTR_CREATE, XATTR_REPLACE}; + use rustpython_host_env::posix::{XATTR_CREATE, XATTR_REPLACE}; #[cfg(any(target_os = "android", target_os = "linux", target_os = "netbsd"))] #[pyattr] - use libc::O_RSYNC; + use rustpython_host_env::os::O_RSYNC; #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] #[pyattr] - use libc::{ + use rustpython_host_env::posix::{ MFD_ALLOW_SEALING, MFD_CLOEXEC, MFD_HUGE_MASK, MFD_HUGETLB, POSIX_FADV_DONTNEED, POSIX_FADV_NOREUSE, POSIX_FADV_NORMAL, POSIX_FADV_RANDOM, POSIX_FADV_SEQUENTIAL, POSIX_FADV_WILLNEED, @@ -97,11 +108,11 @@ pub mod module { #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox", unix))] #[pyattr] - use libc::{RTLD_LAZY, RTLD_NOW, WNOHANG}; + use rustpython_host_env::posix::{RTLD_LAZY, RTLD_NOW, WNOHANG}; #[cfg(any(target_os = "android", target_os = "macos", target_os = "redox", unix))] #[pyattr] - use libc::RTLD_GLOBAL; + use rustpython_host_env::posix::RTLD_GLOBAL; #[cfg(any( target_os = "android", @@ -110,7 +121,7 @@ pub mod module { target_os = "redox" ))] #[pyattr] - use libc::O_PATH; + use rustpython_host_env::os::O_PATH; #[cfg(any( target_os = "android", @@ -119,7 +130,7 @@ pub mod module { target_os = "netbsd" ))] #[pyattr] - use libc::{ + use rustpython_host_env::posix::{ EFD_CLOEXEC, EFD_NONBLOCK, EFD_SEMAPHORE, TFD_CLOEXEC, TFD_NONBLOCK, TFD_TIMER_ABSTIME, TFD_TIMER_CANCEL_ON_SET, }; @@ -131,7 +142,7 @@ pub mod module { target_os = "netbsd" ))] #[pyattr] - use libc::{GRND_NONBLOCK, GRND_RANDOM}; + use rustpython_host_env::posix::{GRND_NONBLOCK, GRND_RANDOM}; #[cfg(any( target_os = "android", @@ -141,7 +152,7 @@ pub mod module { unix ))] #[pyattr] - use libc::{F_OK, R_OK, W_OK, X_OK}; + use rustpython_host_env::os::{F_OK, R_OK, W_OK, X_OK}; #[cfg(any( target_os = "android", @@ -151,7 +162,7 @@ pub mod module { unix ))] #[pyattr] - use libc::O_NONBLOCK; + use rustpython_host_env::os::O_NONBLOCK; #[cfg(any( target_os = "android", @@ -161,7 +172,7 @@ pub mod module { target_os = "netbsd" ))] #[pyattr] - use libc::O_DSYNC; + use rustpython_host_env::os::O_DSYNC; #[cfg(any( target_os = "dragonfly", @@ -171,7 +182,7 @@ pub mod module { target_os = "netbsd" ))] #[pyattr] - use libc::SCHED_OTHER; + use rustpython_host_env::posix::SCHED_OTHER; #[cfg(any( target_os = "android", @@ -181,7 +192,7 @@ pub mod module { target_os = "macos" ))] #[pyattr] - use libc::{RTLD_NODELETE, SEEK_DATA, SEEK_HOLE}; + use rustpython_host_env::posix::{RTLD_NODELETE, SEEK_DATA, SEEK_HOLE}; #[cfg(any( target_os = "android", @@ -191,7 +202,7 @@ pub mod module { target_os = "netbsd" ))] #[pyattr] - use libc::O_DIRECT; + use rustpython_host_env::os::O_DIRECT; #[cfg(any( target_os = "dragonfly", @@ -201,7 +212,7 @@ pub mod module { target_os = "redox" ))] #[pyattr] - use libc::{O_EXLOCK, O_FSYNC, O_SHLOCK}; + use rustpython_host_env::os::{O_EXLOCK, O_FSYNC, O_SHLOCK}; #[cfg(any( target_os = "android", @@ -212,7 +223,7 @@ pub mod module { unix ))] #[pyattr] - use libc::RTLD_LOCAL; + use rustpython_host_env::posix::RTLD_LOCAL; #[cfg(any( target_os = "android", @@ -223,7 +234,7 @@ pub mod module { unix ))] #[pyattr] - use libc::WUNTRACED; + use rustpython_host_env::posix::WUNTRACED; #[cfg(any( target_os = "android", @@ -234,11 +245,22 @@ pub mod module { target_os = "netbsd" ))] #[pyattr] - use libc::{ - CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, CLD_TRAPPED, O_SYNC, P_ALL, - P_PGID, P_PID, SCHED_FIFO, SCHED_RR, + use rustpython_host_env::posix::{ + CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, CLD_TRAPPED, P_ALL, P_PGID, + P_PID, SCHED_FIFO, SCHED_RR, }; + #[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd" + ))] + #[pyattr] + use rustpython_host_env::os::O_SYNC; + #[cfg(any( target_os = "android", target_os = "dragonfly", @@ -249,7 +271,7 @@ pub mod module { unix ))] #[pyattr] - use libc::O_DIRECTORY; + use rustpython_host_env::os::O_DIRECTORY; #[cfg(any( target_os = "android", @@ -261,10 +283,30 @@ pub mod module { target_os = "redox" ))] #[pyattr] - use libc::{ - F_LOCK, F_TEST, F_TLOCK, F_ULOCK, O_ASYNC, O_NDELAY, O_NOCTTY, RTLD_NOLOAD, WEXITED, - WNOWAIT, WSTOPPED, - }; + use rustpython_host_env::fcntl::{F_LOCK, F_TEST, F_TLOCK, F_ULOCK}; + #[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox" + ))] + #[pyattr] + use rustpython_host_env::posix::{RTLD_NOLOAD, WEXITED, WNOWAIT, WSTOPPED}; + + #[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox" + ))] + #[pyattr] + use rustpython_host_env::os::{O_ASYNC, O_NDELAY, O_NOCTTY}; #[cfg(any( target_os = "android", @@ -277,7 +319,20 @@ pub mod module { unix ))] #[pyattr] - use libc::{O_CLOEXEC, WCONTINUED}; + use rustpython_host_env::posix::WCONTINUED; + + #[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "redox", + unix + ))] + #[pyattr] + use rustpython_host_env::os::O_CLOEXEC; #[pyattr] use rustpython_host_env::posix::{ diff --git a/crates/vm/src/vm/interpreter.rs b/crates/vm/src/vm/interpreter.rs index fc088d2a9..20510a115 100644 --- a/crates/vm/src/vm/interpreter.rs +++ b/crates/vm/src/vm/interpreter.rs @@ -1858,19 +1858,29 @@ for _ in range(40): fn eval_breaker_tripped_when_stop_requested_and_stop_bit_clear() { let interp = Interpreter::without_stdlib(Default::default()); interp.enter(|vm| { - crate::signal::clear_stop_bit(); assert!( crate::vm::thread::set_stop_requested_for_current_thread(true), "current thread has no stop_requested flag" ); - crate::signal::clear_stop_bit(); - let pending = crate::signal::eval_breaker_pending(); - let tripped = vm.eval_breaker_tripped(); + // STOP_BIT is process-wide; a parallel stop-the-world test can + // set it between the clear and the load. Retry until this thread + // observes it clear, then sample `eval_breaker_tripped`. + let (stop_bit, tripped) = { + let mut stop_bit = true; + let mut tripped = false; + for _ in 0..10_000 { + crate::signal::clear_stop_bit(); + stop_bit = crate::signal::stop_bit_set(); + tripped = vm.eval_breaker_tripped(); + if !stop_bit { + break; + } + std::thread::yield_now(); + } + (stop_bit, tripped) + }; crate::vm::thread::set_stop_requested_for_current_thread(false); - assert!( - !pending, - "STOP_BIT or another process-wide breaker bit was set" - ); + assert!(!stop_bit, "process-wide STOP_BIT was set"); assert!(tripped); }); }