diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 21df08597..b13ab0e45 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -263,8 +263,8 @@ jobs: - run: cargo check -Z build-std --target=mipsel-unknown-linux-gnu --features=all-apis # Temporarily disable due to build errors on nightly. # - run: cargo check -Z build-std --target=mips64el-unknown-linux-gnuabi64 --features=all-apis - - run: cargo check -Z build-std --target=powerpc-unknown-linux-musl --features=all-apis - - run: cargo check -Z build-std --target=powerpc64le-unknown-linux-musl --features=all-apis + - run: cargo check -Z build-std --target=powerpc-unknown-linux-musl --features=all-apis --all-targets + - run: cargo check -Z build-std --target=powerpc64le-unknown-linux-musl --features=all-apis --all-targets - run: cargo check -Z build-std --target=armv7k-apple-watchos --features=all-apis diff --git a/build.rs b/build.rs index 0bde91294..04f1e9c92 100644 --- a/build.rs +++ b/build.rs @@ -174,7 +174,7 @@ fn main() { || (os == "freebsd" && arch == "x86") || os == "haiku" || env == "gnu" - || (env == "musl" && arch == "x86") + || env == "musl" || (arch == "aarch64" && os == "linux" && abi == Ok("ilp32".to_string()))) { use_feature("fix_y2038"); diff --git a/src/backend/libc/time/syscalls.rs b/src/backend/libc/time/syscalls.rs index 8c730cef0..cfd931868 100644 --- a/src/backend/libc/time/syscalls.rs +++ b/src/backend/libc/time/syscalls.rs @@ -433,11 +433,11 @@ fn timerfd_settime_old( }, it_value: Timespec { tv_sec: old_result - .it_interval + .it_value .tv_sec .try_into() .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: old_result.it_interval.tv_nsec as _, + tv_nsec: old_result.it_value.tv_nsec as _, }, }) } @@ -506,11 +506,11 @@ fn timerfd_gettime_old(fd: BorrowedFd<'_>) -> io::Result { }, it_value: Timespec { tv_sec: old_result - .it_interval + .it_value .tv_sec .try_into() .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: old_result.it_interval.tv_nsec as _, + tv_nsec: old_result.it_value.tv_nsec as _, }, }) } diff --git a/src/termios/types.rs b/src/termios/types.rs index cadbc4767..f78d37906 100644 --- a/src/termios/types.rs +++ b/src/termios/types.rs @@ -32,7 +32,10 @@ pub struct Termios { /// Line discipline. #[doc(alias = "c_line")] - #[cfg(not(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64"))))] + #[cfg(not(all( + any(linux_raw, target_env = "musl"), + any(target_arch = "powerpc", target_arch = "powerpc64") + )))] #[cfg(any( linux_like, target_env = "newlib", @@ -53,7 +56,10 @@ pub struct Termios { /// Line discipline. // On PowerPC, this field comes after `c_cc`. #[doc(alias = "c_line")] - #[cfg(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64")))] + #[cfg(all( + any(linux_raw, target_env = "musl"), + any(target_arch = "powerpc", target_arch = "powerpc64") + ))] pub line_discipline: c::cc_t, /// See the `input_speed` and `set_input_seed` functions. diff --git a/tests/time/timerfd.rs b/tests/time/timerfd.rs index 961441a52..7012dff82 100644 --- a/tests/time/timerfd.rs +++ b/tests/time/timerfd.rs @@ -85,3 +85,70 @@ fn test_timerfd_with_interval() { assert_eq!(set.it_interval.tv_sec, new.it_interval.tv_sec); assert_eq!(set.it_interval.tv_nsec, new.it_interval.tv_nsec); } + +/// Check that it_interval and it_value are reported correctly +#[test] +fn test_timerfd_it_value() { + let fd = match timerfd_create(TimerfdClockId::Monotonic, TimerfdFlags::CLOEXEC) { + Ok(fd) => fd, + Err(rustix::io::Errno::NOSYS) => return, + Err(err) => Err(err).unwrap(), + }; + + // A relative timer far enough in the future that it won't expire during + // the test, even under slow emulation. + let set = Itimerspec { + it_interval: Timespec { + tv_sec: 1, + tv_nsec: 200001, + }, + it_value: Timespec { + tv_sec: 1000, + tv_nsec: 0, + }, + }; + // Generous lower bound for the remaining time. + let min_remaining = Timespec { + tv_sec: set.it_value.tv_sec / 2, + tv_nsec: 0, + }; + + let check = |what: &str, spec: &Itimerspec| { + assert_eq!(spec.it_interval, set.it_interval, "{what}: it_interval"); + assert!( + (0..1_000_000_000).contains(&spec.it_value.tv_nsec), + "{what}: it_value.tv_nsec out of range: {:?}", + spec.it_value + ); + assert!( + spec.it_value <= set.it_value, + "{what}: it_value {:?} exceeds the armed value {:?}", + spec.it_value, + set.it_value + ); + assert!( + spec.it_value > min_remaining, + "{what}: it_value {:?} too small; expected more than {:?}", + spec.it_value, + min_remaining + ); + }; + + // A freshly created timer is disarmed. + let old = timerfd_settime(&fd, TimerfdTimerFlags::empty(), &set).unwrap(); + assert_eq!(old.it_value, Timespec::default(), "initial it_value"); + + let cur = timerfd_gettime(&fd).unwrap(); + check("timerfd_gettime", &cur); + + // Re-arm: the returned old value should be the pending timer and + // it can't have more time remaining than observed above. + let old = timerfd_settime(&fd, TimerfdTimerFlags::empty(), &set).unwrap(); + check("timerfd_settime old value", &old); + assert!( + old.it_value <= cur.it_value, + "remaining time increased: {:?} -> {:?}", + cur.it_value, + old.it_value + ); +}