Skip to content

Commit d8bd8de

Browse files
committedMar 5, 2014
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
1 parent 8334dd4 commit d8bd8de

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed
 

‎src/libnative/io/timer_other.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,15 @@ impl Timer {
218218
}
219219

220220
pub fn sleep(ms: u64) {
221-
// FIXME: this can fail because of EINTR, what do do?
222-
let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) };
221+
let mut to_sleep = libc::timespec {
222+
tv_sec: (ms / 1000) as libc::time_t,
223+
tv_nsec: ((ms % 1000) * 1000000) as libc::c_long,
224+
};
225+
while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 {
226+
if os::errno() as int != libc::EINTR as int {
227+
fail!("failed to sleep, but not because of EINTR?");
228+
}
229+
}
223230
}
224231

225232
fn inner(&mut self) -> ~Inner {

‎src/libnative/io/timer_timerfd.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
//! why).
2424
//!
2525
//! As with timer_other, timers just using sleep() do not use the timerfd at
26-
//! all. They remove the timerfd from the worker thread and then invoke usleep()
27-
//! to block the calling thread.
26+
//! all. They remove the timerfd from the worker thread and then invoke
27+
//! nanosleep() to block the calling thread.
2828
//!
2929
//! As with timer_other, all units in this file are in units of millseconds.
3030
@@ -183,8 +183,15 @@ impl Timer {
183183
}
184184

185185
pub fn sleep(ms: u64) {
186-
// FIXME: this can fail because of EINTR, what do do?
187-
let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) };
186+
let mut to_sleep = libc::timespec {
187+
tv_sec: (ms / 1000) as libc::time_t,
188+
tv_nsec: ((ms % 1000) * 1000000) as libc::c_long,
189+
};
190+
while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 {
191+
if os::errno() as int != libc::EINTR as int {
192+
fail!("failed to sleep, but not because of EINTR?");
193+
}
194+
}
188195
}
189196

190197
fn remove(&mut self) {

‎src/libstd/libc.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3682,6 +3682,7 @@ pub mod funcs {
36823682
use libc::types::common::c95::c_void;
36833683
use libc::types::os::arch::c95::{c_char, c_int, c_long, c_uint};
36843684
use libc::types::os::arch::c95::{size_t};
3685+
use libc::types::os::common::posix01::timespec;
36853686
use libc::types::os::arch::posix01::utimbuf;
36863687
use libc::types::os::arch::posix88::{gid_t, off_t, pid_t};
36873688
use libc::types::os::arch::posix88::{ssize_t, uid_t};
@@ -3731,6 +3732,7 @@ pub mod funcs {
37313732
pub fn setuid(uid: uid_t) -> c_int;
37323733
pub fn sleep(secs: c_uint) -> c_uint;
37333734
pub fn usleep(secs: c_uint) -> c_int;
3735+
pub fn nanosleep(rqtp: *timespec, rmtp: *mut timespec) -> c_int;
37343736
pub fn sysconf(name: c_int) -> c_long;
37353737
pub fn tcgetpgrp(fd: c_int) -> pid_t;
37363738
pub fn ttyname(fd: c_int) -> *c_char;

0 commit comments

Comments
 (0)
Please sign in to comment.