Skip to content

Commit 2987c76

Browse files
committed
fix and test order of TLS dtors and thread joining
1 parent 46e264c commit 2987c76

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

src/shims/tls.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
328328
/// schedules them one by one each time it is called and reenables the
329329
/// thread so that it can be executed normally by the main execution loop.
330330
///
331-
/// FIXME: we do not support yet deallocation of thread local statics.
332-
/// Issue: https://github.com/rust-lang/miri/issues/1369
333-
///
334331
/// Note: we consistently run TLS destructors for all threads, including the
335332
/// main thread. However, it is not clear that we should run the TLS
336333
/// destructors for the main thread. See issue:
@@ -367,6 +364,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
367364

368365
// All dtors done!
369366
this.machine.tls.delete_all_thread_tls(active_thread);
367+
this.thread_terminated();
370368

371369
Ok(())
372370
}

src/thread.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,20 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
410410
None
411411
}
412412

413+
/// Handles thread termination of the active thread: wakes up threads joining on this one,
414+
/// and deallocated thread-local statics.
415+
///
416+
/// This is called from `tls.rs` after handling the TLS dtors.
417+
fn thread_terminated(&mut self) {
418+
for (i, thread) in self.threads.iter_enumerated_mut() {
419+
// Check if we need to unblock any threads.
420+
if thread.state == ThreadState::BlockedOnJoin(self.active_thread) {
421+
trace!("unblocking {:?} because {:?} terminated", i, self.active_thread);
422+
thread.state = ThreadState::Enabled;
423+
}
424+
}
425+
}
426+
413427
/// Decide which action to take next and on which thread.
414428
///
415429
/// The currently implemented scheduling policy is the one that is commonly
@@ -421,13 +435,6 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
421435
// checks whether the thread has popped all its stack and if yes, sets
422436
// the thread state to terminated).
423437
if self.threads[self.active_thread].check_terminated() {
424-
// Check if we need to unblock any threads.
425-
for (i, thread) in self.threads.iter_enumerated_mut() {
426-
if thread.state == ThreadState::BlockedOnJoin(self.active_thread) {
427-
trace!("unblocking {:?} because {:?} terminated", i, self.active_thread);
428-
thread.state = ThreadState::Enabled;
429-
}
430-
}
431438
return Ok(SchedulingAction::ExecuteDtors);
432439
}
433440
if self.threads[MAIN_THREAD].state == ThreadState::Terminated {
@@ -660,4 +667,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
660667
let this = self.eval_context_mut();
661668
this.machine.threads.schedule()
662669
}
670+
671+
#[inline]
672+
fn thread_terminated(&mut self) {
673+
self.eval_context_mut().machine.threads.thread_terminated()
674+
}
663675
}

tests/run-pass/concurrency/tls_lib_drop.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ struct TestCell {
99

1010
impl Drop for TestCell {
1111
fn drop(&mut self) {
12-
println!("Dropping: {}", self.value.borrow())
12+
for _ in 0..10 { thread::yield_now(); }
13+
println!("Dropping: {} (should be before 'Continue main 1').", self.value.borrow())
1314
}
1415
}
1516

@@ -28,7 +29,7 @@ fn check_destructors() {
2829
})
2930
.join()
3031
.unwrap();
31-
println!("Continue main.")
32+
println!("Continue main 1.")
3233
}
3334

3435
struct JoinCell {
@@ -37,8 +38,9 @@ struct JoinCell {
3738

3839
impl Drop for JoinCell {
3940
fn drop(&mut self) {
41+
for _ in 0..10 { thread::yield_now(); }
4042
let join_handle = self.value.borrow_mut().take().unwrap();
41-
println!("Joining: {}", join_handle.join().unwrap());
43+
println!("Joining: {} (should be before 'Continue main 2').", join_handle.join().unwrap());
4244
}
4345
}
4446

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Dropping: 5
2-
Continue main.
1+
Dropping: 5 (should be before 'Continue main 1').
2+
Continue main 1.
3+
Joining: 7 (should be before 'Continue main 2').
34
Continue main 2.
4-
Joining: 7

0 commit comments

Comments
 (0)