Skip to content

Commit

Permalink
leak_tls param for terminate_active_thread()
Browse files Browse the repository at this point in the history
  • Loading branch information
max-heller committed Nov 10, 2023
1 parent 94c74de commit 80f17ca
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 21 deletions.
36 changes: 16 additions & 20 deletions src/concurrency/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// See if this thread can do something else.
match this.run_on_stack_empty()? {
Poll::Pending => {} // keep going
Poll::Ready(()) => this.terminate_active_thread()?,
Poll::Ready(()) => this.terminate_active_thread(false)?,
}
}
}
Expand All @@ -1066,11 +1066,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}

/// Handles thread termination of the active thread: wakes up threads joining on this one,
/// and deallocated thread-local statics.
/// and deallocates thread-local statics (unless `leak_tls` is set, in which case the thread's
/// TLS are marked as static roots for leakage analysis).
///
/// This is called by the eval loop when a thread's on_stack_empty returns `Ready`.
#[inline]
fn terminate_active_thread(&mut self) -> InterpResult<'tcx> {
fn terminate_active_thread(&mut self, leak_tls: bool) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let thread = this.active_thread_mut();
assert!(thread.stack.is_empty(), "only threads with an empty stack can be terminated");
Expand All @@ -1079,24 +1080,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let current_span = this.machine.current_span();
let thread_local_allocations =
this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span);
match this.get_active_thread() {
// For main thread, add thread-local statics to static roots and skip deallocating
// backing memory
ThreadId(0) =>
for ptr in thread_local_allocations {
if let Some(alloc) = ptr.provenance.get_alloc_id() {
trace!(
"Main thread thread-local static stored as static root: {:?}",
alloc
);
this.machine.static_roots.push(alloc);
}
},
if leak_tls {
// Add thread-local statics to static roots and skip deallocating backing memory
for ptr in thread_local_allocations {
if let Some(alloc) = ptr.provenance.get_alloc_id() {
trace!("Thread-local static leaked and stored as static root: {:?}", alloc);
this.machine.static_roots.push(alloc);
}
}
} else {
// Deallocate backing memory of thread-local statics
ThreadId(_) =>
for ptr in thread_local_allocations {
this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?;
},
for ptr in thread_local_allocations {
this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?;
}
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ impl MainThreadState {
let exit_code = this.read_target_isize(&ret_place)?;
// Need to call this ourselves since we are not going to return to the scheduler
// loop, and we want the main thread TLS to not show up as memory leaks.
this.terminate_active_thread()?;
this.terminate_active_thread(true)?;
// Stop interpreter loop.
throw_machine_stop!(TerminationInfo::Exit { code: exit_code, leak_check: true });
}
Expand Down

0 comments on commit 80f17ca

Please sign in to comment.