diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 8af1a8ac608..ae837f8e165 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -716,7 +716,9 @@ fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>( } } - pub fn leak_report(&self) -> usize { + /// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation + /// are not considered leaked. Leaks whose kind `may_leak()` returns true are not reported. + pub fn leak_report(&self, static_roots: &[AllocId]) -> usize { // Collect the set of allocations that are *reachable* from `Global` allocations. let reachable = { let mut reachable = FxHashSet::default(); @@ -724,6 +726,7 @@ pub fn leak_report(&self) -> usize { let mut todo: Vec<_> = self.alloc_map.filter_map_collect(move |&id, &(kind, _)| { if Some(kind) == global_kind { Some(id) } else { None } }); + todo.extend(static_roots); while let Some(id) = todo.pop() { if reachable.insert(id) { // This is a new allocation, add its relocations to `todo`. diff --git a/src/libstd/sys/windows/thread_local_key.rs b/src/libstd/sys/windows/thread_local_key.rs index e0bb102b3af..0bd9600b6f2 100644 --- a/src/libstd/sys/windows/thread_local_key.rs +++ b/src/libstd/sys/windows/thread_local_key.rs @@ -110,6 +110,16 @@ struct Node { next: *mut Node, } +#[cfg(miri)] +extern "Rust" { + /// Miri-provided extern function to mark the block `ptr` points to as a "root" + /// for some static memory. This memory and everything reachable by it is not + /// considered leaking even if it still exists when the program terminates. + /// + /// `ptr` has to point to the beginning of an allocated block. + fn miri_static_root(ptr: *const u8); +} + unsafe fn register_dtor(key: Key, dtor: Dtor) { let mut node = Box::new(Node { key, dtor, next: ptr::null_mut() }); @@ -117,7 +127,12 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) { loop { node.next = head; match DTORS.compare_exchange(head, &mut *node, SeqCst, SeqCst) { - Ok(_) => return mem::forget(node), + Ok(_) => { + #[cfg(miri)] + miri_static_root(&*node as *const _ as *const u8); + + return mem::forget(node); + } Err(cur) => head = cur, } }