about summary refs log tree commit diff
path: root/src/libnative
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-03-04 17:40:45 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-03-05 09:11:10 -0800
commitd8bd8de82e19702ad26fff704ff9a4890ebe1bf7 (patch)
treea4eb4b305a72fd8cd1e19d49a8d91179566a25c7 /src/libnative
parent8334dd445fb10089a68808e7895f0c00d6fd0b3e (diff)
downloadrust-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.rs11
-rw-r--r--src/libnative/io/timer_timerfd.rs15
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) {