]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #19577: aidancully/master
authorAlex Crichton <alex@alexcrichton.com>
Tue, 9 Dec 2014 17:24:39 +0000 (09:24 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 9 Dec 2014 17:24:39 +0000 (09:24 -0800)
pthread_key_create can be 0.
addresses issue #19567.

src/libstd/sys/common/thread_local.rs

index 370d74cc5e1898da87af6ce1e999025cfb3b833a..3eb0e3f46cb90e81cdb229ecb0251e18ad5d291b 100644 (file)
@@ -185,7 +185,23 @@ unsafe fn key(&self) -> imp::Key {
     }
 
     unsafe fn lazy_init(&self) -> uint {
-        let key = imp::create(self.dtor);
+        // POSIX allows the key created here to be 0, but the compare_and_swap
+        // below relies on using 0 as a sentinel value to check who won the
+        // race to set the shared TLS key. As far as I know, there is no
+        // guaranteed value that cannot be returned as a posix_key_create key,
+        // so there is no value we can initialize the inner key with to
+        // prove that it has not yet been set. As such, we'll continue using a
+        // value of 0, but with some gyrations to make sure we have a non-0
+        // value returned from the creation routine.
+        // FIXME: this is clearly a hack, and should be cleaned up.
+        let key1 = imp::create(self.dtor);
+        let key = if key1 != 0 {
+            key1
+        } else {
+            let key2 = imp::create(self.dtor);
+            imp::destroy(key1);
+            key2
+        };
         assert!(key != 0);
         match self.inner.key.compare_and_swap(0, key as uint, atomic::SeqCst) {
             // The CAS succeeded, so we've created the actual key