Merge branch 'sleep-intr' into 'master'

Make nanosleep and sleep handle interrupts correctly, plus fix alarm

See merge request redox-os/relibc!605
This commit is contained in:
Jeremy Soller
2025-01-31 21:10:15 +00:00
3 changed files with 52 additions and 14 deletions
+16 -5
View File
@@ -84,11 +84,13 @@ pub extern "C" fn alarm(seconds: c_uint) -> c_uint {
},
..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, &timer, &mut timer) } < 0 {
let secs = if unsafe { sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut otimer) } < 0 {
0
} else {
timer.it_value.tv_sec as c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 }
otimer.it_value.tv_sec as c_uint + if otimer.it_value.tv_usec > 0 { 1 } else { 0 }
};
platform::ERRNO.set(errno_backup);
@@ -788,9 +790,18 @@ pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
tv_sec: seconds as time_t,
tv_nsec: 0,
};
let rmtp = ptr::null_mut();
unsafe { Sys::nanosleep(&rqtp, rmtp).map(|()| 0).or_minus_one_errno() };
0
let mut rmtp = timespec {
tv_sec: 0,
tv_nsec: 0,
};
// If sleep() returns because the requested time has elapsed, the value returned shall be 0.
// If sleep() returns due to delivery of a signal, the return value shall be the "unslept" amount
// (the requested time minus the time actually slept) in seconds.
match unsafe { Sys::nanosleep(&rqtp, &mut rmtp) } {
Err(Errno(EINTR)) => rmtp.tv_sec as c_uint,
r => 0,
}
}
#[no_mangle]
+13 -8
View File
@@ -18,8 +18,8 @@ use crate::{
header::{
dirent::dirent,
errno::{
EBADF, EBADFD, EBADR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS, EOPNOTSUPP,
EPERM, ERANGE,
EBADF, EBADFD, EBADR, EINTR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS,
EOPNOTSUPP, EPERM, ERANGE,
},
fcntl, limits,
sys_mman::{MAP_ANONYMOUS, MAP_FAILED, PROT_READ, PROT_WRITE},
@@ -698,14 +698,19 @@ impl Pal for Sys {
} else {
redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
}
syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)?;
unsafe {
if !rmtp.is_null() {
(*rmtp).tv_sec = redox_rmtp.tv_sec as time_t;
(*rmtp).tv_nsec = redox_rmtp.tv_nsec as c_long;
match syscall::nanosleep(&redox_rqtp, &mut redox_rmtp) {
Ok(_) => Ok(()),
Err(Error { errno: EINTR }) => {
unsafe {
if !rmtp.is_null() {
(*rmtp).tv_sec = redox_rmtp.tv_sec as time_t;
(*rmtp).tv_nsec = redox_rmtp.tv_nsec as c_long;
}
};
Err(Errno(EINTR))
}
Err(Error { errno: e }) => Err(Errno(e)),
}
Ok(())
}
fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int> {
+23 -1
View File
@@ -1,14 +1,36 @@
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include "test_helpers.h"
int main(void) {
int usleep(useconds_t);
void handler(int _s)
{
(void)_s;
}
int main(void)
{
// sleep has no error codes and doesn't set errno
unsigned int unslept = sleep(2);
printf("unslept: %u\n", unslept);
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
sigaction(SIGALRM, &sa, NULL);
alarm(2);
unslept = sleep(10);
if (unslept < 7)
{
printf("after alarm, unslept too short: %u\n", unslept);
exit(EXIT_FAILURE);
}
int us_status = usleep(1000);
ERROR_IF(usleep, us_status, == -1);
UNEXP_IF(usleep, us_status, != 0);