]> git.lizzy.rs Git - rust.git/commitdiff
std: Ignore dtors_in_dtors_in_dtors on OSX
authorAlex Crichton <alex@alexcrichton.com>
Fri, 29 Jan 2016 21:46:47 +0000 (13:46 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 29 Jan 2016 21:46:47 +0000 (13:46 -0800)
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

index ca0f10315625304313699bbf75ca67268cf68965..d1f5cf81c038da88f5ceb3c8c27a680f9c64840f 100644 (file)
 ///     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<T: 'static> {
     // This outer `LocalKey<T>` type is what's going to be stored in statics,
@@ -602,7 +622,12 @@ fn drop(&mut self) {
         }).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<Option<S1>> = UnsafeCell::new(None));