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 /src/libnative | |
| 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
Diffstat (limited to 'src/libnative')
| -rw-r--r-- | src/libnative/io/timer_other.rs | 11 | ||||
| -rw-r--r-- | src/libnative/io/timer_timerfd.rs | 15 |
2 files changed, 20 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) { |
