`rustc_thread_pool::scope` can return before all scoped jobs finish if a later panic value panics on drop
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
scope can unwind before a slower scoped job has finished.
scope() should not return by unwind until every scoped job has completed but scope() returns after about 100 ms while the slower job finishes later and writes through the scoped borrow
That violates this property
Repro below:
---cargo
[package]
edition = "2021"
[dependencies]
rustc-rayon-core = "0.5.1" # or rustc_thread_pool = { path = "/path/to/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/rustc-src/rust/compiler/rustc_thread_pool" }
---
use std::panic::{self, AssertUnwindSafe};
use std::thread;
use std::time::Duration;
use rustc_thread_pool::ThreadPoolBuilder;
struct PanicOnDrop;
impl Drop for PanicOnDrop {
fn drop(&mut self) {
panic!("drop panic");
}
}
fn main() {
panic::set_hook(Box::new(|_| {}));
let pool = ThreadPoolBuilder::new().num_threads(2).build().unwrap();
let mut data = Box::new(0usize);
let result = panic::catch_unwind(AssertUnwindSafe(|| {
pool.scope(|scope| {
let slot: &mut usize = &mut data;
scope.spawn(|_| panic!("job panic"));
scope.spawn(move |_| {
thread::sleep(Duration::from_millis(350));
*slot = 1;
});
thread::sleep(Duration::from_millis(100));
panic::panic_any(PanicOnDrop);
});
}));
println!("caught={}", result.is_err());
std::mem::forget(result);
drop(data);
thread::sleep(Duration::from_millis(500));
}
$ RUSTFLAGS=-Zsanitizer=address ASAN_OPTIONS=halt_on_error=1 cargo +nightly -Zscript -q main.rs
caught=true
=================================================================
==33659==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000150 at pc 0x0001043a0c60 bp 0x00016bc65400 sp 0x00016bc653f8
WRITE of size 8 at 0x602000000150 thread T1
#0 0x0001043a0c5c in _RNCNCNCNvCs9umYB8D3b62_4main4mains_00s_0B7_ main.rs:39
#1 0x0001043a6694 in _RNCNCINvMNtCsa2rZXaaU2X0_10rayon_core5scopeNtB7_5Scope5spawnNCNCNCNvCs9umYB8D3b62_4main4mains_00s_0E00B14_ mod.rs:531
#2 0x0001043a417c in _RNvXsn_NtNtCs3LtjeOwDatA_4core5panic11unwind_safeINtB5_16AssertUnwindSafeNCNCINvMNtCsa2rZXaaU2X0_10rayon_core5scopeNtB1h_5Scope5spawnNCNCNCNvCs9umYB8D3b62_4main4mains_00s_0E00EINtNtNtB9_3ops8function6FnOnceuE9call_onceB2f_ unwind_safe.rs:275
#3 0x0001043a446c in _RINvNvNtCs2RIEs2EU4b4_3std9panicking12catch_unwind7do_callINtNtNtCs3LtjeOwDatA_4core5panic11unwind_safe16AssertUnwindSafeNCNCINvMNtCsa2rZXaaU2X0_10rayon_core5scopeNtB23_5Scope5spawnNCNCNCNvCs9umYB8D3b62_4main4mains_00s_0E00EuEB31_ panicking.rs:575
#4 0x0001043a1f30 in __rust_try+0x1c (main:arm64+0x100001f30)
#5 0x0001043a1a44 in _RINvNtCs2RIEs2EU4b4_3std9panicking12catch_unwinduINtNtNtCs3LtjeOwDatA_4core5panic11unwind_safe16AssertUnwindSafeNCNCINvMNtCsa2rZXaaU2X0_10rayon_core5scopeNtB1U_5Scope5spawnNCNCNCNvCs9umYB8D3b62_4main4mains_00s_0E00EEB2S_ panicking.rs:543...
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in compiler/rustc_thread_pool/src/scope/mod.rs, especially the property around lines 293-296, and run the provided reproducer with the rustc-rayon-core dependency. Trace how scope handles multiple panics and the later panic value's drop. Done means scope does not unwind until every scoped job has completed, avoiding the demonstrated late write through the scoped borrow.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100