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
|
// 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.
|
// 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)?;
|
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()?;
|
ecx.run_windows_tls_dtors()?;
|
||||||
Ok(return_code)
|
Ok(return_code)
|
||||||
})();
|
})();
|
||||||
|
@ -6,7 +6,6 @@ use std::collections::HashSet;
|
|||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use rustc_index::vec::Idx;
|
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_target::abi::{Size, HasDataLayout};
|
use rustc_target::abi::{Size, HasDataLayout};
|
||||||
|
|
||||||
@ -201,7 +200,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let active_thread = this.get_active_thread()?;
|
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");
|
assert!(!this.machine.tls.dtors_running.contains(&active_thread), "running TLS dtors twice");
|
||||||
this.machine.tls.dtors_running.insert(active_thread);
|
this.machine.tls.dtors_running.insert(active_thread);
|
||||||
// Windows has a special magic linker section that is run on certain events.
|
// 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
|
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?
|
/// Has the given thread terminated?
|
||||||
fn has_terminated(&self, thread_id: ThreadId) -> bool {
|
fn has_terminated(&self, thread_id: ThreadId) -> bool {
|
||||||
self.threads[thread_id].state == ThreadState::Terminated
|
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())
|
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]
|
#[inline]
|
||||||
fn has_terminated(&self, thread_id: ThreadId) -> InterpResult<'tcx, bool> {
|
fn has_terminated(&self, thread_id: ThreadId) -> InterpResult<'tcx, bool> {
|
||||||
let this = self.eval_context_ref();
|
let this = self.eval_context_ref();
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
// ignore-windows: Concurrency on Windows is not supported yet.
|
// 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)]
|
#![feature(thread_local_internals)]
|
||||||
|
|
||||||
use std::cell::RefCell;
|
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