Skip to content
New issue

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

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

Already on GitHub? Sign in 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
Collaborator

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
Contributor

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
Contributor

bors commented Jun 20, 2016

📌 Commit f053216 has been approved by alexcrichton

@bors
Copy link
Contributor

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants