-
Notifications
You must be signed in to change notification settings - Fork 352
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #2931 - max-heller:issue-2881, r=RalfJung
Treat thread-local statics on main thread as static roots for leakage analysis Miri currently treats allocations as leaked if they're only referenced in thread-local statics. For threads other than the main thread, this is correct, since the thread can terminate before the program does, but references in the main thread's locals should be treated as living for the duration of the program since the thread lives for the duration of the program. This PR adds thread-local statics and TLS keys as "static roots" for leakage analysis, but does not yet bless the example program from #2881. See #2881 (comment) Closes #2881
- Loading branch information
Showing
7 changed files
with
148 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//@error-in-other-file: memory leaked | ||
//@normalize-stderr-test: ".*│.*" -> "$$stripped$$" | ||
|
||
use std::cell::Cell; | ||
|
||
pub fn main() { | ||
thread_local! { | ||
static TLS: Cell<Option<&'static i32>> = Cell::new(None); | ||
} | ||
|
||
std::thread::spawn(|| { | ||
TLS.with(|cell| { | ||
cell.set(Some(Box::leak(Box::new(123)))); | ||
}); | ||
}) | ||
.join() | ||
.unwrap(); | ||
|
||
// Imagine the program running for a long time while the thread is gone | ||
// and this memory still sits around, unused -- leaked. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
error: memory leaked: ALLOC (Rust heap, size: 4, align: 4), allocated here: | ||
--> RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
| | ||
LL | __rust_alloc(layout.size(), layout.align()) | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `<std::alloc::Global as std::alloc::Allocator>::allocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `alloc::alloc::exchange_malloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `std::boxed::Box::<i32>::new` at RUSTLIB/alloc/src/boxed.rs:LL:CC | ||
note: inside closure | ||
--> $DIR/leak_in_lib_tls.rs:LL:CC | ||
| | ||
LL | cell.set(Some(Box::leak(Box::new(123)))); | ||
| ^^^^^^^^^^^^^ | ||
= note: inside `std::thread::LocalKey::<std::cell::Cell<std::option::Option<&i32>>>::try_with::<{closure@$DIR/leak_in_lib_tls.rs:LL:CC}, ()>` at RUSTLIB/std/src/thread/local.rs:LL:CC | ||
= note: inside `std::thread::LocalKey::<std::cell::Cell<std::option::Option<&i32>>>::with::<{closure@$DIR/leak_in_lib_tls.rs:LL:CC}, ()>` at RUSTLIB/std/src/thread/local.rs:LL:CC | ||
note: inside closure | ||
--> $DIR/leak_in_lib_tls.rs:LL:CC | ||
| | ||
LL | / TLS.with(|cell| { | ||
LL | | cell.set(Some(Box::leak(Box::new(123)))); | ||
LL | | }); | ||
| |__________^ | ||
|
||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | ||
|
||
note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
//@error-in-other-file: memory leaked | ||
//@normalize-stderr-test: ".*│.*" -> "$$stripped$$" | ||
|
||
#![feature(thread_local)] | ||
|
||
use std::cell::Cell; | ||
|
||
/// Ensure that leaks through `thread_local` statics *not in the main thread* | ||
/// are detected. | ||
pub fn main() { | ||
#[thread_local] | ||
static TLS: Cell<Option<&'static i32>> = Cell::new(None); | ||
|
||
std::thread::spawn(|| { | ||
TLS.set(Some(Box::leak(Box::new(123)))); | ||
}) | ||
.join() | ||
.unwrap(); | ||
|
||
// Imagine the program running for a long time while the thread is gone | ||
// and this memory still sits around, unused -- leaked. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
error: memory leaked: ALLOC (Rust heap, size: 4, align: 4), allocated here: | ||
--> RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
| | ||
LL | __rust_alloc(layout.size(), layout.align()) | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `<std::alloc::Global as std::alloc::Allocator>::allocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `alloc::alloc::exchange_malloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC | ||
= note: inside `std::boxed::Box::<i32>::new` at RUSTLIB/alloc/src/boxed.rs:LL:CC | ||
note: inside closure | ||
--> $DIR/leak_in_static_tls.rs:LL:CC | ||
| | ||
LL | TLS.set(Some(Box::leak(Box::new(123)))); | ||
| ^^^^^^^^^^^^^ | ||
|
||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | ||
|
||
note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check | ||
|
||
error: aborting due to previous error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//@ignore-target-windows: Windows uses a different mechanism for `thread_local!` | ||
#![feature(thread_local)] | ||
|
||
use std::cell::Cell; | ||
|
||
// Thread-local variables in the main thread are basically like `static` (they live | ||
// as long as the program does), so make sure we treat them the same for leak purposes. | ||
pub fn main() { | ||
thread_local! { | ||
static TLS_KEY: Cell<Option<&'static i32>> = Cell::new(None); | ||
} | ||
|
||
TLS_KEY.with(|cell| { | ||
cell.set(Some(Box::leak(Box::new(123)))); | ||
}); | ||
|
||
#[thread_local] | ||
static TLS: Cell<Option<&'static i32>> = Cell::new(None); | ||
|
||
TLS.set(Some(Box::leak(Box::new(123)))); | ||
} |