diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-03-04 17:40:45 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-03-05 09:11:10 -0800 |
| commit | d8bd8de82e19702ad26fff704ff9a4890ebe1bf7 (patch) | |
| tree | a4eb4b305a72fd8cd1e19d49a8d91179566a25c7 | |
| parent | 8334dd445fb10089a68808e7895f0c00d6fd0b3e (diff) | |
| download | rust-d8bd8de82e19702ad26fff704ff9a4890ebe1bf7.tar.gz rust-d8bd8de82e19702ad26fff704ff9a4890ebe1bf7.zip | |
native: Move from usleep() to nanosleep()
Using nanosleep() allows us to gracefully recover from EINTR because on error it fills in the second parameter with the remaining time to sleep. Closes #12689
| -rw-r--r-- | src/libnative/io/timer_other.rs | 11 | ||||
| -rw-r--r-- | src/libnative/io/timer_timerfd.rs | 15 | ||||
| -rw-r--r-- | src/libstd/libc.rs | 2 |
3 files changed, 22 insertions, 6 deletions
diff --git a/src/libnative/io/timer_other.rs b/src/libnative/io/timer_other.rs index 9d700550863..d7323ddf499 100644 --- a/src/libnative/io/timer_other.rs +++ b/src/libnative/io/timer_other.rs @@ -218,8 +218,15 @@ impl Timer { } pub fn sleep(ms: u64) { - // FIXME: this can fail because of EINTR, what do do? - let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) }; + let mut to_sleep = libc::timespec { + tv_sec: (ms / 1000) as libc::time_t, + tv_nsec: ((ms % 1000) * 1000000) as libc::c_long, + }; + while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 { + if os::errno() as int != libc::EINTR as int { + fail!("failed to sleep, but not because of EINTR?"); + } + } } fn inner(&mut self) -> ~Inner { diff --git a/src/libnative/io/timer_timerfd.rs b/src/libnative/io/timer_timerfd.rs index 68277efc9b7..55301b6f7c8 100644 --- a/src/libnative/io/timer_timerfd.rs +++ b/src/libnative/io/timer_timerfd.rs @@ -23,8 +23,8 @@ //! why). //! //! As with timer_other, timers just using sleep() do not use the timerfd at -//! all. They remove the timerfd from the worker thread and then invoke usleep() -//! to block the calling thread. +//! all. They remove the timerfd from the worker thread and then invoke +//! nanosleep() to block the calling thread. //! //! As with timer_other, all units in this file are in units of millseconds. @@ -183,8 +183,15 @@ impl Timer { } pub fn sleep(ms: u64) { - // FIXME: this can fail because of EINTR, what do do? - let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) }; + let mut to_sleep = libc::timespec { + tv_sec: (ms / 1000) as libc::time_t, + tv_nsec: ((ms % 1000) * 1000000) as libc::c_long, + }; + while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 { + if os::errno() as int != libc::EINTR as int { + fail!("failed to sleep, but not because of EINTR?"); + } + } } fn remove(&mut self) { diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index 7096765d9fc..d10fa7684e8 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -3682,6 +3682,7 @@ pub mod funcs { use libc::types::common::c95::c_void; use libc::types::os::arch::c95::{c_char, c_int, c_long, c_uint}; use libc::types::os::arch::c95::{size_t}; + use libc::types::os::common::posix01::timespec; use libc::types::os::arch::posix01::utimbuf; use libc::types::os::arch::posix88::{gid_t, off_t, pid_t}; use libc::types::os::arch::posix88::{ssize_t, uid_t}; @@ -3731,6 +3732,7 @@ pub mod funcs { pub fn setuid(uid: uid_t) -> c_int; pub fn sleep(secs: c_uint) -> c_uint; pub fn usleep(secs: c_uint) -> c_int; + pub fn nanosleep(rqtp: *timespec, rmtp: *mut timespec) -> c_int; pub fn sysconf(name: c_int) -> c_long; pub fn tcgetpgrp(fd: c_int) -> pid_t; pub fn ttyname(fd: c_int) -> *c_char; |
