From b960de0984cec27989746eec6fa706b3a7b46ad3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 29 Jan 2016 13:46:47 -0800 Subject: [PATCH] std: Ignore dtors_in_dtors_in_dtors on OSX This test has been deadlocking and causing problems on the bots basically since its inception. Some memory safety issues were fixed in 987dc84b, but the deadlocks remained afterwards unfortunately. After some investigation, I've concluded that this is just a situation where OSX is not guaranteed to run destructors. The fix in 987dc84b observed that OSX was rewriting the backing TLS memory to its initial state during destruction while we weren't looking, and this would have the effect of canceling the destructors of any other initialized TLS slots. While very difficult to pin down, this is basically what I assume is happening here, so there doesn't seem to really be anythig we can do to ensure the test robustly passes on OSX, so just ignore it for now. --- src/libstd/thread/local.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index ca0f103156253..d1f5cf81c038d 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -56,6 +56,26 @@ use mem; /// assert_eq!(*f.borrow(), 2); /// }); /// ``` +/// +/// # Platform-specific behavior +/// +/// Note that a "best effort" is made to ensure that destructors for types +/// stored in thread local storage are run, but not all platforms can gurantee +/// that destructors will be run for all types in thread local storage. For +/// example, there are a number of known caveats where destructors are not run: +/// +/// 1. On Unix systems when pthread-based TLS is being used, destructors will +/// not be run for TLS values on the main thread when it exits. Note that the +/// application will exit immediately after the main thread exits as well. +/// 2. On all platforms it's possible for TLS to re-initialize other TLS slots +/// during destruction. Some platforms ensure that this cannot happen +/// infinitely by preventing re-initialization of any slot that has been +/// destroyed, but not all platforms have this guard. Those platforms that do +/// not guard typically have a synthetic limit after which point no more +/// destructors are run. +/// 3. On OSX, initializing TLS during destruction of other TLS slots can +/// sometimes cancel *all* destructors for the current thread, whether or not +/// the slots have already had their destructors run or not. #[stable(feature = "rust1", since = "1.0.0")] pub struct LocalKey { // This outer `LocalKey` type is what's going to be stored in statics, @@ -602,7 +622,12 @@ mod tests { }).join().ok().unwrap(); } + // Note that this test will deadlock if TLS destructors aren't run (this + // requires the destructor to be run to pass the test). OSX has a known bug + // where dtors-in-dtors may cancel other destructors, so we just ignore this + // test on OSX. #[test] + #[cfg_attr(target_os = "macos", ignore)] fn dtors_in_dtors_in_dtors() { struct S1(Sender<()>); thread_local!(static K1: UnsafeCell> = UnsafeCell::new(None));