diff --git a/src/header/time/mod.rs b/src/header/time/mod.rs index fd0ba15035..b534dc5274 100644 --- a/src/header/time/mod.rs +++ b/src/header/time/mod.rs @@ -66,6 +66,9 @@ pub(crate) struct timer_internal_t { pub caller_thread: crate::pthread::OsTid, // relibc handles it_interval, not the kernel pub next_wake_time: itimerspec, + // When non-zero, timer_routine delivers SIGALRM via kill(process_pid, sig) + // instead of rlct_kill (thread-specific). Used by alarm(). + pub process_pid: platform::types::pid_t, } /// See . diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index aa31284d81..c4d5f17b00 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -24,7 +24,7 @@ use crate::{ }, out::Out, platform::{ - self, ERRNO, Pal, Sys, + self, ERRNO, Pal, PalSignal, Sys, types::{ c_char, c_int, c_long, c_short, c_uint, c_ulonglong, c_void, gid_t, off_t, pid_t, size_t, ssize_t, suseconds_t, time_t, uid_t, useconds_t, @@ -137,28 +137,7 @@ pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int { /// See . #[unsafe(no_mangle)] pub extern "C" fn alarm(seconds: c_uint) -> c_uint { - // TODO setitimer is unimplemented on Redox and obsolete - let timer = sys_time::itimerval { - it_value: timeval { - tv_sec: time_t::from(seconds), - tv_usec: 0, - }, - ..Default::default() - }; - let mut otimer = sys_time::itimerval::default(); - - let errno_backup = platform::ERRNO.get(); - let secs = - if unsafe { sys_time::setitimer(sys_time::ITIMER_REAL, &raw const timer, &raw mut otimer) } - < 0 - { - 0 - } else { - otimer.it_value.tv_sec as c_uint + if otimer.it_value.tv_usec > 0 { 1 } else { 0 } - }; - platform::ERRNO.set(errno_backup); - - secs + Sys::alarm(seconds) } /// See . diff --git a/src/platform/pal/signal.rs b/src/platform/pal/signal.rs index 52670daa6f..b8ed26acea 100644 --- a/src/platform/pal/signal.rs +++ b/src/platform/pal/signal.rs @@ -4,8 +4,9 @@ use crate::{ header::{ bits_time::timespec, signal::{sigaction, siginfo_t, sigset_t, sigval, stack_t}, - sys_time::itimerval, + sys_time::{self, itimerval}, }, + platform, }; pub trait PalSignal: Pal { @@ -21,6 +22,32 @@ pub trait PalSignal: Pal { fn setitimer(which: c_int, new: &itimerval, old: Option<&mut itimerval>) -> Result<()>; + /// See . + /// + /// Default implementation uses setitimer(ITIMER_REAL). Platforms that do not + /// support setitimer (e.g. Redox) must override this. + fn alarm(seconds: c_uint) -> c_uint { + use crate::header::sys_select::timeval; + + let timer = itimerval { + it_value: timeval { + tv_sec: time_t::from(seconds), + tv_usec: 0, + }, + ..Default::default() + }; + let mut otimer = itimerval::default(); + + let errno_backup = platform::ERRNO.get(); + let secs = if Self::setitimer(sys_time::ITIMER_REAL, &timer, Some(&mut otimer)).is_err() { + 0 + } else { + otimer.it_value.tv_sec as c_uint + if otimer.it_value.tv_usec > 0 { 1 } else { 0 } + }; + platform::ERRNO.set(errno_backup); + secs + } + fn sigaction(sig: c_int, act: Option<&sigaction>, oact: Option<&mut sigaction>) -> Result<()>; unsafe fn sigaltstack(ss: Option<&stack_t>, old_ss: Option<&mut stack_t>) -> Result<()>; diff --git a/tests/Makefile.tests.mk b/tests/Makefile.tests.mk index 1f591dabc2..7ace459d3a 100644 --- a/tests/Makefile.tests.mk +++ b/tests/Makefile.tests.mk @@ -159,6 +159,7 @@ EXPECT_NAMES=\ time/timegm \ time/tzset \ unistd/access \ + unistd/alarm \ unistd/constants \ unistd/confstr \ unistd/dup \