From 1355574bebb5f7cb572bb7399964f91101e8852e Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Mon, 27 Apr 2020 14:00:39 -0700 Subject: [PATCH] Delete remaining tls entries after all destructors completed. --- src/shims/tls.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/shims/tls.rs b/src/shims/tls.rs index a98a8025641..d5ea430dd27 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -211,6 +211,14 @@ impl<'tcx> TlsData<'tcx> { false } } + + /// Delete all TLS entries for the given thread. This function should be + /// called after all TLS destructors have already finished. + fn delete_all_thread_tls(&mut self, thread_id: ThreadId) { + for TlsEntry { data, .. } in self.keys.values_mut() { + data.remove(&thread_id); + } + } } impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} @@ -271,8 +279,9 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx Ok(()) } - /// Schedule a pthread TLS destructor. - fn schedule_pthread_tls_dtors(&mut self) -> InterpResult<'tcx> { + /// Schedule a pthread TLS destructor. Returns `true` if found + /// a destructor to schedule, and `false` otherwise. + fn schedule_pthread_tls_dtors(&mut self) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); let active_thread = this.get_active_thread()?; @@ -300,11 +309,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx )?; this.enable_thread(active_thread)?; - return Ok(()); + return Ok(true); } this.machine.tls.dtors_running.get_mut(&active_thread).unwrap().last_dtor_key = None; - Ok(()) + Ok(false) } } @@ -322,16 +331,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); let active_thread = this.get_active_thread()?; - if this.tcx.sess.target.target.target_os == "windows" { + let finished = if this.tcx.sess.target.target.target_os == "windows" { if !this.machine.tls.set_dtors_running_for_thread(active_thread) { this.schedule_windows_tls_dtors()?; } + true } else { this.machine.tls.set_dtors_running_for_thread(active_thread); // The macOS thread wide destructor runs "before any TLS slots get // freed", so do that first. this.schedule_macos_tls_dtor()?; - this.schedule_pthread_tls_dtors()?; + this.schedule_pthread_tls_dtors()? + }; + + if finished { + this.machine.tls.delete_all_thread_tls(active_thread); } Ok(())