-
Notifications
You must be signed in to change notification settings - Fork 13k
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
thread::unpark: Avoid notifying with mutex locked. #54806
Conversation
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
src/libstd/thread/mod.rs
Outdated
// up) and when it actually waits on `cvar` which is when it can | ||
// receive `notify_one`. Fortunately it has `lock` locked at this stage | ||
// so we can acquire `lock` to wait until it is ready to receive the | ||
// notification. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH I do not find this comment very helpful, but that may be just wording: It is unclear what the "which is" refers to; I first thought it refers to the period ("There is a period ... which is"). So please split this first sentence into at least two sentences.
Also it should say explicitly what the bad behavior we want to avoid is: When we call notify_one
, we must be sure the other thread already went to sleep (it's fine if it has already woken up again), if it is still about to go to sleep that's no good as the notification just gets lost.
src/libstd/thread/mod.rs
Outdated
// Releasing `lock` before the call to `notify_one` means that when the | ||
// parked thread wakes it doesn't get woken only to have to wait for us | ||
// to release `lock`. | ||
self.inner.lock.lock().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to let-bind it, use e.g. let _ = ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't that be counterproductive? Since this PR would be literally a NFC then?
But I think this line should be something like drop(self.inner.lock.lock().unwrap());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let _ = ...
and let _x = ...
are very different. The former drops immediately.
But you are right, for extra clarity it is probably better to call drop
explicitly.
LGTM, but I'd prefer another set of eyes on this. @alexcrichton? @carllerche? |
Functionally this makes sense to me, I agree we don't need to hold the lock over the notification, we just need to acquire the lock to ensure the other thread, if any, is asleep and will receive the notification. |
Thanks, I'll make the changes next week when I'm back from holiday. By the way, what's the policy for squashing fix commits in a PR? I seem to remember reading some time ago rust preferred not to, but now I can't find where that was stated. |
Either way's fine, whichever you prefer! |
Ping from triage @parched: what is the status of this PR? |
This means when the other thread wakes it can continue right away instead of having to wait for the mutex. Also add some comments explaining why the mutex needs to be locked in the first place.
Seems we got two people agreeing this makes sense, so let's land it. :) @bors r+ |
📌 Commit d3e71e4 has been approved by |
⌛ Testing commit d3e71e4 with merge c61baf7c0f8e842dc73948ba3b132f43ae61442b... |
💔 Test failed - status-appveyor |
Timed out after 3h. @bors retry |
thread::unpark: Avoid notifying with mutex locked. This means when the other thread wakes it can continue right away instead of having to wait for the mutex. Also add some comments explaining why the mutex needs to be locked in the first place. This is a follow up to #54174 I did some tests with relacy [here](https://gist.github.com/parched/b7fb88c97755a81e5cb9f9048a15f7fb) (This PR is InnerV2). If anyone can think of some other test case worth adding let me know. r? @RalfJung
☀️ Test successful - status-appveyor, status-travis |
This PR broke Tokio's sanitization tests in: tokio-rs/tokio#722 I can reproduce the reported data race locally on my machine on
It can only be due to this PR. The reported data race is between a write in The PR looks correct to me so I don't know what to make of this. It might be some kind of synchronization inside pthread's condvar that thread sanitizer is not understanding. I'll probably just add this case to the TSAN suppressions file. cc @carllerche |
I think there's been bugs with TSAN in the past around (maybe?) fenches which |
I think Alex is correct, it would be nice to get a minimal reproducer if possible to verify though. |
This means when the other thread wakes it can continue right away
instead of having to wait for the mutex.
Also add some comments explaining why the mutex needs to be locked in
the first place.
This is a follow up to #54174
I did some tests with relacy here (This PR is InnerV2). If anyone can think of some other test case worth adding let me know.
r? @RalfJung