From 07659b7f5f04288e342bfb3f37b2af648422df6e Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Mon, 27 Jul 2026 07:12:27 +0900 Subject: [PATCH] Remove round-7 stubs: todo!(), unimplemented!(), silent no-ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six items fixed from the round-7 relibc stub scan: 1. set_scheduler todo!() (mod.rs:1487) — replaced panic with proper policy validation: SCHED_OTHER is a no-op (kernel default), RT policies (FIFO/RR) return ENOSYS (need kernel support Redox lacks), invalid policies return EINVAL. Made posix_spawnattr_t.policy pub(crate) so the platform layer can read it. 2. F_SETLKW silent no-op (mod.rs:474) — merged into the F_SETLK | F_OFD_SETLK match arm. Redox's StdFsCallKind::Lock blocks at the kernel level, so F_SETLKW uses the same code path as F_SETLK. The is_ofd flag correctly evaluates to false for F_SETLKW. 3. relative_to_absolute_foffset silent (0,0) (mod.rs:1989) — implemented SEEK_CUR via lseek(fd, 0, SEEK_CUR) and SEEK_END via fstat(fd). Both apply the same negative-len normalization as SEEK_SET. Invalid whence values now return EINVAL instead of corrupting offsets. 4. setitimer ENOSYS (signal.rs:96) — replaced todo_skip! stub with a real implementation using a process-global POSIX timer (timer_create with CLOCK_REALTIME + SIGEV_SIGNAL/SIGALRM). Supports intervals (periodic timers), disarm (value=0), and old-value retrieval. getitimer also updated to read from the real timer instead of returning defaults. 5. ptrace unimplemented!() (ptrace.rs:127,138,279) — replaced three panics on aarch64/x86/riscv64 with Err(io::Error::from_raw_os_error( ENOSYS)). The caller maps this to Errno(ENOSYS), the proper POSIX response for architecture-specific ptrace on unsupported arches. 6. todo_skip! macro verified (macros.rs:47) — confirmed it is non-panicking (logs via log::info! and evaluates to ()). The setitimer stub was safe in that it returned ENOSYS after the log, but the real implementation is strictly better. --- src/header/spawn/spawn_attr.rs | 2 +- src/platform/redox/mod.rs | 46 +++++++++++--- src/platform/redox/ptrace.rs | 35 +++++------ src/platform/redox/signal.rs | 110 ++++++++++++++++++++++++++------- 4 files changed, 140 insertions(+), 53 deletions(-) diff --git a/src/header/spawn/spawn_attr.rs b/src/header/spawn/spawn_attr.rs index 2c541585eb..4f3d95a911 100644 --- a/src/header/spawn/spawn_attr.rs +++ b/src/header/spawn/spawn_attr.rs @@ -41,7 +41,7 @@ pub struct posix_spawnattr_t { pub param: sched_param, pub flags: c_short, pub pgroup: c_int, - policy: c_int, + pub(crate) policy: c_int, pub sigdefault: sigset_t, pub sigmask: sigset_t, } diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index a1844ba887..1e73aa2d39 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -38,6 +38,7 @@ use crate::{ }, limits::{self}, pthread::{pthread_cancel, pthread_create}, + sched::{SCHED_FIFO, SCHED_OTHER, SCHED_RR}, signal::{NSIG, SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD, SIGRTMIN, sigevent}, stdio::RENAME_NOREPLACE, stdlib::posix_memalign, @@ -56,7 +57,7 @@ use crate::{ time::{ CLOCK_MONOTONIC, CLOCK_REALTIME, TIMER_ABSTIME, itimerspec, timer_internal_t, timespec, }, - unistd::{F_OK, R_OK, SEEK_CUR, SEEK_SET, W_OK, X_OK}, + unistd::{F_OK, R_OK, SEEK_CUR, SEEK_END, SEEK_SET, W_OK, X_OK}, }, io::{self, BufReader, prelude::*}, iter::NulTerminated, @@ -367,7 +368,7 @@ impl Pal for Sys { fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result { match cmd { - F_SETLK | F_OFD_SETLK => { + F_SETLK | F_OFD_SETLK | F_SETLKW => { let is_ofd = cmd == F_OFD_SETLK; let flock = unsafe { &mut *(args as *mut flock) }; @@ -471,8 +472,6 @@ impl Pal for Sys { return Ok(0); } - F_SETLKW => log::warn!("F_SETLKW: not yet implemented"), - _ => {} } @@ -1484,7 +1483,15 @@ impl Pal for Sys { Ok(()) } }; - let set_scheduler = || -> Result<()> { todo!() }; + let set_scheduler = || -> Result<()> { + // SCHED_OTHER is the kernel default (no-op); RT policies need + // kernel support Redox lacks, so ENOSYS per POSIX. + match attr.policy { + SCHED_OTHER => Ok(()), + SCHED_FIFO | SCHED_RR => Err(Errno(ENOSYS)), + _ => Err(Errno(EINVAL)), + } + }; // scheduling paramters must be set regardless of whether the flag POSIX_SPAWN_SETSCHEDPARAM is set if flags.contains(Flags::POSIX_SPAWN_SETSCHEDULER) { @@ -1986,12 +1993,31 @@ impl Sys { assert!(len >= 0); Ok((start, len)) } - // FIXME: andypython: SEEK_CUR, SEEK_END + c if c == i32::from(SEEK_CUR) || c == i32::from(SEEK_END) => { + let base = if c == i32::from(SEEK_CUR) { + syscall::lseek(fd, 0, SEEK_CUR as usize)? as off_t + } else { + let mut st: stat = unsafe { mem::zeroed() }; + unsafe { libredox::fstat(fd, &raw mut st) }?; + st.st_size as off_t + }; + + let abs_start = base + start; + let (abs_start, abs_len) = if len < 0 { + (abs_start + len, -len) + } else { + (abs_start, len) + }; + + if abs_start < 0 { + return Err(Errno(EINVAL)); + } + + assert!(abs_len >= 0); + Ok((abs_start, abs_len)) + } c => { - log::warn!( - "Sys::relative_to_absolute_foffset: whence={whence} not yet implemented" - ); - Ok((0, 0)) + return Err(Errno(EINVAL)); } } } diff --git a/src/platform/redox/ptrace.rs b/src/platform/redox/ptrace.rs index 4ac81a00c7..482df1f4d3 100644 --- a/src/platform/redox/ptrace.rs +++ b/src/platform/redox/ptrace.rs @@ -14,7 +14,7 @@ use crate::{ error::Errno, fs::File, header::{ - errno::{self as errnoh, EIO}, + errno::{self as errnoh, EIO, ENOSYS}, fcntl, }, io, @@ -118,24 +118,22 @@ pub fn get_session( #[cfg(target_arch = "aarch64")] unsafe fn inner_ptrace( - request: c_int, - pid: pid_t, - addr: *mut c_void, - data: *mut c_void, + _request: c_int, + _pid: pid_t, + _addr: *mut c_void, + _data: *mut c_void, ) -> io::Result { - //TODO: aarch64 - unimplemented!("inner_ptrace not implemented on aarch64"); + Err(io::Error::from_raw_os_error(ENOSYS)) } #[cfg(target_arch = "x86")] unsafe fn inner_ptrace( - request: c_int, - pid: pid_t, - addr: *mut c_void, - data: *mut c_void, + _request: c_int, + _pid: pid_t, + _addr: *mut c_void, + _data: *mut c_void, ) -> io::Result { - //TODO: x86 - unimplemented!("inner_ptrace not implemented on x86"); + Err(io::Error::from_raw_os_error(ENOSYS)) } #[cfg(target_arch = "x86_64")] @@ -270,13 +268,12 @@ unsafe fn inner_ptrace( #[cfg(target_arch = "riscv64")] fn inner_ptrace( - request: c_int, - pid: pid_t, - addr: *mut c_void, - data: *mut c_void, + _request: c_int, + _pid: pid_t, + _addr: *mut c_void, + _data: *mut c_void, ) -> io::Result { - //TODO: riscv64 - unimplemented!("inner_ptrace not implemented on riscv64"); + Err(io::Error::from_raw_os_error(ENOSYS)) } impl PalPtrace for Sys { diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 6d29af132b..6885c131ba 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -8,13 +8,16 @@ use crate::{ error::{Errno, Result}, header::{ bits_sigset_t::sigset_t, - errno::{EINVAL, ENOSYS}, + errno::{EINVAL}, signal::{ - SIG_BLOCK, SIG_DFL, SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, SS_ONSTACK, - sigaction, siginfo_t, sigval, stack_t, ucontext_t, + SIGALRM, SIG_BLOCK, SIG_DFL, SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, + SS_ONSTACK, SIGEV_SIGNAL, sigaction, sigevent, siginfo_t, sigval, stack_t, + ucontext_t, }, - time::timespec, + time::{CLOCK_REALTIME, itimerspec, timespec}, }, + out::Out, + sync::Mutex, }; use core::mem::offset_of; use redox_protocols::protocol::ProcKillTarget; @@ -22,6 +25,11 @@ use redox_rt::signal::{ PosixStackt, SigStack, Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler, }; +struct ItimerTimer(timer_t); +unsafe impl Send for ItimerTimer {} + +static ITIMER_REAL_TIMER: Mutex> = Mutex::new(None); + const _: () = { #[track_caller] const fn assert_eq(a: usize, b: usize) { @@ -47,20 +55,21 @@ const _: () = { impl PalSignal for Sys { #[allow(deprecated)] fn getitimer(which: c_int, out: &mut itimerval) -> Result<()> { - let path = match which { - ITIMER_REAL => "/scheme/itimer/1", - _ => return Err(Errno(EINVAL)), - }; - // TODO: implement setitimer - // let fd = FdGuard::new(redox_rt::sys::open(path, syscall::O_RDONLY | syscall::O_CLOEXEC)?); - // let count = syscall::read(*fd, &mut spec)?; - - let spec = syscall::ITimerSpec::default(); - out.it_interval.tv_sec = spec.it_interval.tv_sec as time_t; - out.it_interval.tv_usec = spec.it_interval.tv_nsec / 1000; - out.it_value.tv_sec = spec.it_value.tv_sec as time_t; - out.it_value.tv_usec = spec.it_value.tv_nsec / 1000; + if which != ITIMER_REAL { + return Err(Errno(EINVAL)); + } + let guard = ITIMER_REAL_TIMER.lock(); + if let Some(ref timer) = *guard { + let mut cur = itimerspec::default(); + Sys::timer_gettime(timer.0, Out::from_mut(&mut cur))?; + out.it_interval.tv_sec = cur.it_interval.tv_sec as time_t; + out.it_interval.tv_usec = (cur.it_interval.tv_nsec / 1000) as suseconds_t; + out.it_value.tv_sec = cur.it_value.tv_sec as time_t; + out.it_value.tv_usec = (cur.it_value.tv_nsec / 1000) as suseconds_t; + } else { + *out = unsafe { core::mem::zeroed() }; + } Ok(()) } @@ -89,12 +98,67 @@ impl PalSignal for Sys { } #[allow(deprecated)] - fn setitimer(which: c_int, _new: &itimerval, old: Option<&mut itimerval>) -> Result<()> { - // TODO: setitimer is no longer part of POSIX and should not be implemented in Redox - // Change the platform-independent implementation to use POSIX timers. - // For Redox, the timer should probably use "/scheme/time" - todo_skip!(0, "setitimer not implemented"); - Err(Errno(ENOSYS)) + fn setitimer(which: c_int, new: &itimerval, old: Option<&mut itimerval>) -> Result<()> { + if which != ITIMER_REAL { + return Err(Errno(EINVAL)); + } + + let mut guard = ITIMER_REAL_TIMER.lock(); + + if let Some(old_out) = old { + if let Some(ref timer) = *guard { + let mut cur = itimerspec::default(); + if Sys::timer_gettime(timer.0, Out::from_mut(&mut cur)).is_ok() { + old_out.it_interval.tv_sec = cur.it_interval.tv_sec as time_t; + old_out.it_interval.tv_usec = + (cur.it_interval.tv_nsec / 1000) as suseconds_t; + old_out.it_value.tv_sec = cur.it_value.tv_sec as time_t; + old_out.it_value.tv_usec = (cur.it_value.tv_nsec / 1000) as suseconds_t; + } else { + *old_out = unsafe { core::mem::zeroed() }; + } + } else { + *old_out = unsafe { core::mem::zeroed() }; + } + } + + let disarm = new.it_value.tv_sec == 0 && new.it_value.tv_usec == 0; + + if disarm { + if let Some(ref timer) = *guard { + let zero = itimerspec::default(); + let _ = Sys::timer_settime(timer.0, 0, &zero, None); + } + return Ok(()); + } + + if guard.is_none() { + let mut evp: sigevent = unsafe { core::mem::zeroed() }; + evp.sigev_notify = SIGEV_SIGNAL; + evp.sigev_signo = SIGALRM as c_int; + let mut timer_id: timer_t = core::ptr::null_mut(); + Sys::timer_create(CLOCK_REALTIME, &evp, Out::from_mut(&mut timer_id))?; + *guard = Some(ItimerTimer(timer_id)); + } + + let timer_id = guard + .as_ref() + .expect("itimer must exist after lazy init") + .0; + + let spec = itimerspec { + it_value: timespec { + tv_sec: new.it_value.tv_sec, + tv_nsec: new.it_value.tv_usec as i64 * 1000, + }, + it_interval: timespec { + tv_sec: new.it_interval.tv_sec, + tv_nsec: new.it_interval.tv_usec as i64 * 1000, + }, + }; + + Sys::timer_settime(timer_id, 0, &spec, None)?; + Ok(()) } fn sigaction(