host_env: export O_* flags, wasm errno, and posix names (#8788)

* host_env: export O_* flags and wasm errno

Re-export open(2) flags from os. wasm32-unknown-unknown uses
Darwin/BSD numbers, matching the guest errno table.

Expand errno_wasm to that table plus strerror.

Assisted-by: Claude

* stdlib: take O_* open flags from host_env

os, posix, and nt re-export the host_env names instead of libc.

Assisted-by: Claude

* host_env: export remaining posix integer names

Publish wait, RTLD, SCHED, SEEK, PRIO, CLD, AT, lockf, and
statvfs flags so posix and os stop taking them from libc.

Assisted-by: Claude

* stdlib: take remaining posix names from host_env

posix and os re-export wait, RTLD, SCHED, SEEK, PRIO, and
statvfs flags from host_env.

Assisted-by: Claude

* host_env: define AT_EACCESS on Android

bionic's libc crate does not export AT_EACCESS. Use the Linux
fcntl value there.

The eval-breaker unit test now waits for STOP_BIT to be clear
instead of requiring the whole process-wide breaker word empty.

Assisted-by: Claude

* vm: gate stop_bit_set to tests

Clippy builds the lib without tests, so the helper and its
re-export were unused.

Assisted-by: Claude
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2026-09-23 08:12:02 +09:00
1 parent 2b8c095e11
commit 01bd5ca370
15 files changed
+509 -87

No files matched your search

+81 -5
View File
@@ -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<String> {
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")
);
}
}
+11
View File
@@ -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};
+1 -1
View File
@@ -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());
}
+8 -8
View File
@@ -82,7 +82,7 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result<ParsedFileMode, FileModeError
}
rwa = true;
mode.insert(FileMode::WRITABLE | FileMode::CREATED);
flags |= libc::O_EXCL | libc::O_CREAT;
flags |= os::O_EXCL | os::O_CREAT;
}
b'r' => {
if rwa {
@@ -97,7 +97,7 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result<ParsedFileMode, FileModeError
}
rwa = true;
mode.insert(FileMode::WRITABLE);
flags |= libc::O_CREAT | libc::O_TRUNC;
flags |= os::O_CREAT | os::O_TRUNC;
}
b'a' => {
if rwa {
@@ -105,7 +105,7 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result<ParsedFileMode, FileModeError
}
rwa = true;
mode.insert(FileMode::WRITABLE | FileMode::APPENDING);
flags |= libc::O_APPEND | libc::O_CREAT;
flags |= os::O_APPEND | os::O_CREAT;
}
b'+' => {
if plus {
@@ -124,20 +124,20 @@ pub fn parse_fileio_mode(mode_str: &str) -> Result<ParsedFileMode, FileModeError
}
if mode.contains(FileMode::READABLE | FileMode::WRITABLE) {
flags |= libc::O_RDWR;
flags |= os::O_RDWR;
} else if mode.contains(FileMode::READABLE) {
flags |= libc::O_RDONLY;
flags |= os::O_RDONLY;
} else {
flags |= libc::O_WRONLY;
flags |= os::O_WRONLY;
}
#[cfg(windows)]
{
flags |= libc::O_BINARY | libc::O_NOINHERIT;
flags |= os::O_BINARY | os::O_NOINHERIT;
}
#[cfg(unix)]
{
flags |= libc::O_CLOEXEC;
flags |= os::O_CLOEXEC;
}
Ok(ParsedFileMode { mode, flags })
+2 -13
View File
@@ -2,19 +2,8 @@ use core::ffi::CStr;
use std::io;
use crate::crt_fd;
const EBADF: i32 = 9;
const EAGAIN: i32 = 11;
const EINTR: i32 = 4;
const EISDIR: i32 = 21;
const O_RDONLY: i32 = 0;
const O_WRONLY: i32 = 1;
const O_RDWR: i32 = 2;
const O_APPEND: i32 = 0x0008;
const O_CREAT: i32 = 0x0200;
const O_TRUNC: i32 = 0x0400;
const O_EXCL: i32 = 0x0800;
use crate::errno::errors::{EAGAIN, EBADF, EINTR, EISDIR};
use crate::os::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+1 -1
View File
@@ -46,7 +46,7 @@ unsafe extern "C" {
}
pub fn setmode_binary(fd: crt_fd::Borrowed<'_>) {
unsafe { suppress_iph!(_setmode(fd, libc::O_BINARY)) };
unsafe { suppress_iph!(_setmode(fd, crate::os::O_BINARY)) };
}
#[must_use]
+8 -2
View File
@@ -136,8 +136,14 @@ impl SemHandle {
unlink: bool,
) -> Result<(Self, Option<String>), 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()));
}
+3 -3
View File
@@ -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),
+131
View File
@@ -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);
}
}
+139
View File
@@ -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,
+7
View File
@@ -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,
+3 -1
View File
@@ -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::{
+4 -8
View File
@@ -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)
+92 -37
View File
@@ -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::{
+18 -8
View File
@@ -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);
});
}