From 266d31126600130999ad6150f621417e17d98e0b Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 2 Nov 2026 10:54:19 +0100 Subject: [PATCH 1/4] fix: Termios line_discipline on PowerPC musl use the PowerPC field order with musl too Signed-off-by: Pepper Gray --- src/termios/types.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) 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. From 0e6abcbf7b9130632cc41cd1b47c858e5aa444fb Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 2 Nov 2026 11:16:04 +0100 Subject: [PATCH 2/4] fix: enable fix_y2038 on all 32bit musl platforms `[cfg(fix_y2038)]` is only enabled for x86, but should be enaled for all 32-bit `musl` architectures. Closes: #1701 Signed-off-by: Pepper Gray --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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"); From cc133fcee8be13f5d0d84ad1dc96c4d7b6b007f8 Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 2 Nov 2026 11:55:12 +0100 Subject: [PATCH 3/4] fix: return it_value from 32-bit timerfd fallbacks The fallbacks filled both output fields from it_interval. - return `it_value` - add a regression test Signed-off-by: Pepper Gray --- src/backend/libc/time/syscalls.rs | 8 ++-- tests/time/timerfd.rs | 68 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) 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/tests/time/timerfd.rs b/tests/time/timerfd.rs index 961441a52..bfb14d46c 100644 --- a/tests/time/timerfd.rs +++ b/tests/time/timerfd.rs @@ -85,3 +85,71 @@ 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 since + // it's on the monotonic clock, it can't have more time remaining than we + // 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 + ); +} From eaad27506c6cfea8cfa8a8584f034433e32bd68a Mon Sep 17 00:00:00 2001 From: Pepper Gray Date: Mon, 2 Nov 2026 11:27:11 +0100 Subject: [PATCH 4/4] ci: extend powerpc/powerpc64le musl check enable all-targets to catch `termios` and `fix_y2038` error Signed-off-by: Pepper Gray --- .github/workflows/main.yml | 4 ++-- tests/time/timerfd.rs | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) 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/tests/time/timerfd.rs b/tests/time/timerfd.rs index bfb14d46c..7012dff82 100644 --- a/tests/time/timerfd.rs +++ b/tests/time/timerfd.rs @@ -141,9 +141,8 @@ fn test_timerfd_it_value() { let cur = timerfd_gettime(&fd).unwrap(); check("timerfd_gettime", &cur); - // Re-arm; the returned old value should be the pending timer, and since - // it's on the monotonic clock, it can't have more time remaining than we - // observed above. + // 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!(