about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2022-10-11 18:37:54 +0900
committerGitHub <noreply@github.com>2022-10-11 18:37:54 +0900
commit919d6bf4468a1e884b2098dc46d2c5424f4497d7 (patch)
tree6a125ac351c7851bcfa0caacda0b0a12d9420ac2 /compiler/rustc_codegen_llvm/src
parente0954cadc8a407bed951ff8d956b76236b7dd97c (diff)
parent78b577c065f71c7ad30a70c8c65c7ff561fee852 (diff)
downloadrust-919d6bf4468a1e884b2098dc46d2c5424f4497d7.tar.gz
rust-919d6bf4468a1e884b2098dc46d2c5424f4497d7.zip
Rollup merge of #102589 - RalfJung:scoped-threads-dangling, r=m-ou-se
scoped threads: pass closure through MaybeUninit to avoid invalid dangling references

The `main` function defined here looks roughly like this, if it were written as a more explicit stand-alone function:
```rust
// Not showing all the `'lifetime` tracking, the point is that
// this closure might live shorter than `thread`.
fn thread(control: ..., closure: impl FnOnce() + 'lifetime) {
    closure();
    control.signal_done();
    // A lot of time can pass here.
}
```
Note that `thread` continues to run even after `signal_done`! Now consider what happens if the `closure` captures a reference of lifetime `'lifetime`:
- The type of `closure` is a struct (the implicit unnameable closure type) with a `&'lifetime mut T` field. References passed to a function are marked with `dereferenceable`, which is LLVM speak for *this reference will remain live for the entire duration of this function*.
- The closure runs, `signal_done` runs. Then -- potentially -- this thread gets scheduled away and the main thread runs, seeing the signal and returning to the user. Now `'lifetime` ends and the memory the reference points to might be deallocated.
- Now we have UB! The reference that as passed to `thread` with the promise of remaining live for the entire duration of the function, actually got deallocated while the function still runs. Oops.

Long-term I think we should be able to use `ManuallyDrop` to fix this without `unsafe`, or maybe a new `MaybeDangling` type. I am working on an RFC for that. But in the mean time it'd be nice to fix this so that Miri with `-Zmiri-retag-fields` (which is needed for "full enforcement" of all the LLVM flags we generate) stops erroring on scoped threads.

Fixes https://github.com/rust-lang/rust/issues/101983
r? `@m-ou-se`
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
0 files changed, 0 insertions, 0 deletions