From d8bd8de82e19702ad26fff704ff9a4890ebe1bf7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 4 Mar 2014 17:40:45 -0800 Subject: 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 --- src/libnative/io/timer_other.rs | 11 +++++++++-- src/libnative/io/timer_timerfd.rs | 15 +++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'src/libnative') 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) { -- cgit 1.4.1-3-g733a5