Skip to content

Commit 9a01c3f

Browse files
author
Vytautas Astrauskas
committed
Clarify comments about TLS destructor handling in Windows, add a test for TLS destructors.
1 parent e4dc356 commit 9a01c3f

File tree

7 files changed

+67
-3
lines changed

7 files changed

+67
-3
lines changed

src/eval.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,8 @@ pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) ->
222222
// Read the return code pointer *before* we run TLS destructors, to assert
223223
// that it was written to by the time that `start` lang item returned.
224224
let return_code = ecx.read_scalar(ret_place.into())?.not_undef()?.to_machine_isize(&ecx)?;
225-
// Global destructors.
225+
// Run Windows destructors. (We do not support concurrency on Windows
226+
// yet, so we run the destructor of the main thread separately.)
226227
ecx.run_windows_tls_dtors()?;
227228
Ok(return_code)
228229
})();

src/shims/tls.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use std::collections::HashSet;
66

77
use log::trace;
88

9-
use rustc_index::vec::Idx;
109
use rustc_middle::ty;
1110
use rustc_target::abi::{Size, HasDataLayout};
1211

@@ -201,7 +200,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
201200
return Ok(());
202201
}
203202
let active_thread = this.get_active_thread()?;
204-
assert_eq!(active_thread.index(), 0, "concurrency on Windows not supported");
203+
assert_eq!(this.get_total_thread_count()?, 1, "concurrency on Windows not supported");
205204
assert!(!this.machine.tls.dtors_running.contains(&active_thread), "running TLS dtors twice");
206205
this.machine.tls.dtors_running.insert(active_thread);
207206
// Windows has a special magic linker section that is run on certain events.

src/thread.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
227227
self.active_thread
228228
}
229229

230+
/// Get the total number of threads that were ever spawn by this program.
231+
fn get_total_thread_count(&self) -> usize {
232+
self.threads.len()
233+
}
234+
230235
/// Has the given thread terminated?
231236
fn has_terminated(&self, thread_id: ThreadId) -> bool {
232237
self.threads[thread_id].state == ThreadState::Terminated
@@ -492,6 +497,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
492497
Ok(this.machine.threads.get_active_thread_id())
493498
}
494499

500+
#[inline]
501+
fn get_total_thread_count(&self) -> InterpResult<'tcx, usize> {
502+
let this = self.eval_context_ref();
503+
Ok(this.machine.threads.get_total_thread_count())
504+
}
505+
495506
#[inline]
496507
fn has_terminated(&self, thread_id: ThreadId) -> InterpResult<'tcx, bool> {
497508
let this = self.eval_context_ref();

tests/compile-fail/concurrency/dangling_tls_lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// ignore-windows: Concurrency on Windows is not supported yet.
22

3+
//! Check that we catch if a thread local is accessed after the thread has
4+
//! terminated.
5+
36
#![feature(thread_local_internals)]
47

58
use std::cell::RefCell;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// ignore-windows: Concurrency on Windows is not supported yet.
2+
3+
//! Check that destructors of the library thread locals are executed immediately
4+
//! after a thread terminates.
5+
6+
#![feature(thread_local_internals)]
7+
8+
use std::cell::RefCell;
9+
use std::thread;
10+
11+
struct TestCell {
12+
value: RefCell<u8>,
13+
}
14+
15+
impl Drop for TestCell {
16+
fn drop(&mut self) {
17+
println!("Dropping: {}", self.value.borrow())
18+
}
19+
}
20+
21+
static A: std::thread::LocalKey<TestCell> = {
22+
#[inline]
23+
fn __init() -> TestCell {
24+
TestCell { value: RefCell::new(0) }
25+
}
26+
27+
unsafe fn __getit() -> Option<&'static TestCell> {
28+
static __KEY: std::thread::__OsLocalKeyInner<TestCell> =
29+
std::thread::__OsLocalKeyInner::new();
30+
__KEY.get(__init)
31+
}
32+
33+
unsafe { std::thread::LocalKey::new(__getit) }
34+
};
35+
36+
fn main() {
37+
thread::spawn(|| {
38+
A.with(|f| {
39+
assert_eq!(*f.value.borrow(), 0);
40+
*f.value.borrow_mut() = 5;
41+
});
42+
})
43+
.join()
44+
.unwrap();
45+
println!("Continue main.")
46+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
warning: thread support is experimental. For example, Miri does not detect data races yet.
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Dropping: 5
2+
Continue main.

0 commit comments

Comments
 (0)