Clarify comments about TLS destructor handling in Windows, add a test for TLS destructors.
This commit is contained in:
parent
e4dc3567f8
commit
9a01c3fa3e
@ -222,7 +222,8 @@ pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) ->
|
||||
// Read the return code pointer *before* we run TLS destructors, to assert
|
||||
// that it was written to by the time that `start` lang item returned.
|
||||
let return_code = ecx.read_scalar(ret_place.into())?.not_undef()?.to_machine_isize(&ecx)?;
|
||||
// Global destructors.
|
||||
// Run Windows destructors. (We do not support concurrency on Windows
|
||||
// yet, so we run the destructor of the main thread separately.)
|
||||
ecx.run_windows_tls_dtors()?;
|
||||
Ok(return_code)
|
||||
})();
|
||||
|
@ -6,7 +6,6 @@ use std::collections::HashSet;
|
||||
|
||||
use log::trace;
|
||||
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty;
|
||||
use rustc_target::abi::{Size, HasDataLayout};
|
||||
|
||||
@ -201,7 +200,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
return Ok(());
|
||||
}
|
||||
let active_thread = this.get_active_thread()?;
|
||||
assert_eq!(active_thread.index(), 0, "concurrency on Windows not supported");
|
||||
assert_eq!(this.get_total_thread_count()?, 1, "concurrency on Windows not supported");
|
||||
assert!(!this.machine.tls.dtors_running.contains(&active_thread), "running TLS dtors twice");
|
||||
this.machine.tls.dtors_running.insert(active_thread);
|
||||
// Windows has a special magic linker section that is run on certain events.
|
||||
|
@ -227,6 +227,11 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
|
||||
self.active_thread
|
||||
}
|
||||
|
||||
/// Get the total number of threads that were ever spawn by this program.
|
||||
fn get_total_thread_count(&self) -> usize {
|
||||
self.threads.len()
|
||||
}
|
||||
|
||||
/// Has the given thread terminated?
|
||||
fn has_terminated(&self, thread_id: ThreadId) -> bool {
|
||||
self.threads[thread_id].state == ThreadState::Terminated
|
||||
@ -492,6 +497,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
Ok(this.machine.threads.get_active_thread_id())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_total_thread_count(&self) -> InterpResult<'tcx, usize> {
|
||||
let this = self.eval_context_ref();
|
||||
Ok(this.machine.threads.get_total_thread_count())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_terminated(&self, thread_id: ThreadId) -> InterpResult<'tcx, bool> {
|
||||
let this = self.eval_context_ref();
|
||||
|
@ -1,5 +1,8 @@
|
||||
// ignore-windows: Concurrency on Windows is not supported yet.
|
||||
|
||||
//! Check that we catch if a thread local is accessed after the thread has
|
||||
//! terminated.
|
||||
|
||||
#![feature(thread_local_internals)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
46
tests/run-pass/concurrency/tls_lib_drop.rs
Normal file
46
tests/run-pass/concurrency/tls_lib_drop.rs
Normal file
@ -0,0 +1,46 @@
|
||||
// ignore-windows: Concurrency on Windows is not supported yet.
|
||||
|
||||
//! Check that destructors of the library thread locals are executed immediately
|
||||
//! after a thread terminates.
|
||||
|
||||
#![feature(thread_local_internals)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::thread;
|
||||
|
||||
struct TestCell {
|
||||
value: RefCell<u8>,
|
||||
}
|
||||
|
||||
impl Drop for TestCell {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping: {}", self.value.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
static A: std::thread::LocalKey<TestCell> = {
|
||||
#[inline]
|
||||
fn __init() -> TestCell {
|
||||
TestCell { value: RefCell::new(0) }
|
||||
}
|
||||
|
||||
unsafe fn __getit() -> Option<&'static TestCell> {
|
||||
static __KEY: std::thread::__OsLocalKeyInner<TestCell> =
|
||||
std::thread::__OsLocalKeyInner::new();
|
||||
__KEY.get(__init)
|
||||
}
|
||||
|
||||
unsafe { std::thread::LocalKey::new(__getit) }
|
||||
};
|
||||
|
||||
fn main() {
|
||||
thread::spawn(|| {
|
||||
A.with(|f| {
|
||||
assert_eq!(*f.value.borrow(), 0);
|
||||
*f.value.borrow_mut() = 5;
|
||||
});
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
println!("Continue main.")
|
||||
}
|
2
tests/run-pass/concurrency/tls_lib_drop.stderr
Normal file
2
tests/run-pass/concurrency/tls_lib_drop.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
warning: thread support is experimental. For example, Miri does not detect data races yet.
|
||||
|
2
tests/run-pass/concurrency/tls_lib_drop.stdout
Normal file
2
tests/run-pass/concurrency/tls_lib_drop.stdout
Normal file
@ -0,0 +1,2 @@
|
||||
Dropping: 5
|
||||
Continue main.
|
Loading…
x
Reference in New Issue
Block a user