Skip to content

Commit

Permalink
Rollup merge of rust-lang#34363 - GuillaumeGomez:sleep, r=alexcrichton
Browse files Browse the repository at this point in the history
Fix overflow error in thread::sleep

Fixes rust-lang#34330

I added a test to have a more clear error inside the function. Since `time_t` is `i64` and we expect `u64`, maybe we should changed the awaited type?
  • Loading branch information
Manishearth authored Jun 22, 2016
2 parents e4ff7f0 + c02414e commit 2aaf6a0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
21 changes: 15 additions & 6 deletions src/libstd/sys/unix/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,25 @@ impl Thread {
}

pub fn sleep(dur: Duration) {
let mut ts = libc::timespec {
tv_sec: dur.as_secs() as libc::time_t,
tv_nsec: dur.subsec_nanos() as libc::c_long,
};
let mut secs = dur.as_secs();
let mut nsecs = dur.subsec_nanos() as libc::c_long;

// If we're awoken with a signal then the return value will be -1 and
// nanosleep will fill in `ts` with the remaining time.
unsafe {
while libc::nanosleep(&ts, &mut ts) == -1 {
assert_eq!(os::errno(), libc::EINTR);
while secs > 0 || nsecs > 0 {
let mut ts = libc::timespec {
tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
tv_nsec: nsecs,
};
secs -= ts.tv_sec as u64;
if libc::nanosleep(&ts, &mut ts) == -1 {
assert_eq!(os::errno(), libc::EINTR);
secs += ts.tv_sec as u64;
nsecs = ts.tv_nsec;
} else {
nsecs = 0;
}
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions src/test/run-pass/sleep.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::thread::{self, sleep};
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::u64;

fn main() {
let finished = Arc::new(Mutex::new(false));
let t_finished = finished.clone();
thread::spawn(move || {
sleep(Duration::new(u64::MAX, 0));
*t_finished.lock().unwrap() = true;
});
sleep(Duration::from_millis(100));
assert_eq!(*finished.lock().unwrap(), false);
}

0 comments on commit 2aaf6a0

Please sign in to comment.