Skip to content

Commit 8e48eae

Browse files
bors[bot]cuviper
andauthored
Merge #992
992: Fix a sleep race with broadcast jobs r=cuviper a=cuviper The sleep code checks `has_injected_jobs` as the final step before blocking the thread, but this was only looking at the normal pool- injected jobs. With `broadcast`, there's now a way to inject jobs directly on each thread, which they should also check individually before going to sleep -- and now they do! Co-authored-by: Josh Stone <[email protected]>
2 parents 4a6e9bf + ab02e68 commit 8e48eae

File tree

5 files changed

+25
-3
lines changed

5 files changed

+25
-3
lines changed

RELEASES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Release rayon-core 1.10.1 (2022-11-18)
2+
3+
- Fixed a race condition with threads going to sleep while a broadcast starts.
4+
15
# Release rayon 1.6.0 / rayon-core 1.10.0 (2022-11-18)
26

37
- The minimum supported `rustc` is now 1.56.

ci/compat-Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rayon-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rayon-core"
3-
version = "1.10.0"
3+
version = "1.10.1"
44
authors = ["Niko Matsakis <[email protected]>",
55
"Josh Stone <[email protected]>"]
66
description = "Core APIs for Rayon"

rayon-core/src/broadcast/test.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,17 @@ fn spawn_broadcast_panic_many() {
200200
assert_eq!(rx.into_iter().count(), 7);
201201
assert_eq!(panic_rx.into_iter().count(), 4);
202202
}
203+
204+
#[test]
205+
fn broadcast_sleep_race() {
206+
let test_duration = time::Duration::from_secs(1);
207+
let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap();
208+
let start = time::Instant::now();
209+
while start.elapsed() < test_duration {
210+
pool.broadcast(|ctx| {
211+
// A slight spread of sleep duration increases the chance that one
212+
// of the threads will race in the pool's idle sleep afterward.
213+
thread::sleep(time::Duration::from_micros(ctx.index() as u64));
214+
});
215+
}
216+
}

rayon-core/src/registry.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,10 @@ impl WorkerThread {
742742
}
743743
}
744744

745+
fn has_injected_job(&self) -> bool {
746+
!self.stealer.is_empty() || self.registry.has_injected_job()
747+
}
748+
745749
/// Wait until the latch is set. Try to keep busy by popping and
746750
/// stealing tasks as necessary.
747751
#[inline]
@@ -779,7 +783,7 @@ impl WorkerThread {
779783
} else {
780784
self.registry
781785
.sleep
782-
.no_work_found(&mut idle_state, latch, || self.registry.has_injected_job())
786+
.no_work_found(&mut idle_state, latch, || self.has_injected_job())
783787
}
784788
}
785789

0 commit comments

Comments
 (0)