From: Alex Crichton Date: Tue, 9 Dec 2014 17:24:39 +0000 (-0800) Subject: rollup merge of #19577: aidancully/master X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=39b57115fbf5d91df3382699b1dbde7ea8716f6c;hp=a09632f7cb19d0fc6526cc6e4f514472809f24ac;p=rust.git rollup merge of #19577: aidancully/master pthread_key_create can be 0. addresses issue #19567. --- diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs index 370d74cc5e1..3eb0e3f46cb 100644 --- a/src/libstd/sys/common/thread_local.rs +++ b/src/libstd/sys/common/thread_local.rs @@ -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