Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix overflow error in thread::sleep #34363

Merged
merged 1 commit into from
Jun 22, 2016
Merged

Conversation

GuillaumeGomez
Copy link
Member

Fixes #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?

@rust-highfive
Copy link
Contributor

r? @brson

(rust_highfive has picked a reviewer for you, use r? to override)

@nagisa
Copy link
Member

nagisa commented Jun 19, 2016

Rather than a test we should just iteratate and call sleep multiple times with duration of up-to the allowed amount.

@@ -125,8 +126,10 @@ impl Thread {
}

pub fn sleep(dur: Duration) {
let secs = dur.as_secs();
assert!(secs <= (u64::MAX >> 1), "secs number is too big");
Copy link
Member

@nagisa nagisa Jun 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error happens because “The rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 million.” u64::MAX >> 1 is not 1000 million and that’s seconds too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, my bad. Disregard me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it still would be more clear if you did something like:

let secs = dur.as_secs() as libc::time_t;
assert!(secs.is_positive(), "...");

Your current approach won’t catch the cases where time_t is i32 (some versions of windows, mips linux etc)

@nagisa
Copy link
Member

nagisa commented Jun 19, 2016

Also needs a regression test. You should either mock-out the nanosleep function or invoke a new thread/process and catch a signal of some sort sent to it by the parent.

@GuillaumeGomez GuillaumeGomez changed the title Add a test inside thread::sleep Fix overflow error in thread::sleep Jun 19, 2016
fn get_secs(secs: &mut u64) -> libc::time_t {
if *secs >= libc::time_t::max_value() as u64 {
*secs -= libc::time_t::max_value() as u64 - 1;
libc::time_t::max_value() - 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why - 1 here and above this line?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It fails if >= 1000000. So I put the max minus one.

@nagisa
Copy link
Member

nagisa commented Jun 19, 2016

r=me with -1 thing explained as a code comment or removed.

@nagisa
Copy link
Member

nagisa commented Jun 19, 2016

cc @alexcrichton

@@ -125,16 +125,32 @@ impl Thread {
}

pub fn sleep(dur: Duration) {
fn get_secs(secs: &mut u64) -> libc::time_t {
if *secs > libc::time_t::max_value() as u64 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this could be:

let amt = cmp::min(libc::time_t::max_value() as u64, *secs);
*secs -= amt;
amt

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a right thing to do.

assert_eq!(os::errno(), libc::EINTR);
}
secs += ts.tv_sec as u64;
nsecs = ts.tv_nsec;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, documentation for nanosleep does not specify what ts contains after a successful call, therefore, in order to be on the safe side, you want to only do this in case the nanosleep call fails and set these fields to 0 otherwise.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea!

@eddyb
Copy link
Member

eddyb commented Jun 20, 2016

@bors r=nagisa f053216

@bors
Copy link
Collaborator

bors commented Jun 20, 2016

⌛ Testing commit f053216 with merge ac9ba4e...

@alexcrichton
Copy link
Member

@bors: r-

Ah there's still a loop that's needed, I'll comment to it.

@alexcrichton
Copy link
Member

@bors: r+

oh nvmd I see, just had to think for a second...

@bors
Copy link
Collaborator

bors commented Jun 20, 2016

📌 Commit f053216 has been approved by alexcrichton

@bors
Copy link
Collaborator

bors commented Jun 20, 2016

💔 Test failed - auto-linux-64-x-android-t

@GuillaumeGomez
Copy link
Member Author

Ah, ualarm isn't defined on android. Do I ignore this platform as well?

@nagisa
Copy link
Member

nagisa commented Jun 20, 2016

What about setitimer which is a newer alternative to the ualarm?

@alexcrichton
Copy link
Member

Or... spawn a thread which sleeps for a smaller amount of time and then exits?

@GuillaumeGomez
Copy link
Member Author

@alexcrichton: I take your solution! :)

@GuillaumeGomez
Copy link
Member Author

Updated.


#![feature(libc)]

extern crate libc;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this and feature and // ignore above can all be removed

@GuillaumeGomez
Copy link
Member Author

Updated.

@alexcrichton
Copy link
Member

@bors: r+ ae544c5b156a56b1a170ea669487fde0c417545a

@GuillaumeGomez
Copy link
Member Author

------------------------------------------
stderr:
------------------------------------------
<anon>:11:1: 11:19 error: use of unstable library feature 'libc': use `libc` from crates.io (see issue #27783)
<anon>:11 extern crate libc;
          ^~~~~~~~~~~~~~~~~~
<anon>:11:1: 11:19 help: add #![feature(libc)] to the crate attributes to enable
error: aborting due to previous error

I put back the feature.

@GuillaumeGomez
Copy link
Member Author

Actually libc was completely useless, I just removed it.

@alexcrichton
Copy link
Member

@bors: r+ c02414e

Manishearth added a commit to Manishearth/rust that referenced this pull request Jun 22, 2016
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?
Manishearth added a commit to Manishearth/rust that referenced this pull request Jun 22, 2016
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?
bors added a commit that referenced this pull request Jun 22, 2016
Rollup of 7 pull requests

- Successful merges: #34190, #34363, #34367, #34383, #34387, #34394, #34404
- Failed merges:
@bors bors merged commit c02414e into rust-lang:master Jun 22, 2016
@GuillaumeGomez GuillaumeGomez deleted the sleep branch June 22, 2016 15:31
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants