Fix a bad bug in folly::ThreadLocal (incorrect using of pthread)
authorAlexander Shaposhnikov <alexshap@fb.com>
Tue, 4 Aug 2015 06:24:18 +0000 (23:24 -0700)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Tue, 4 Aug 2015 07:22:17 +0000 (00:22 -0700)
Summary: Fix incorrect using of pthread in folly::ThreadLocal.

The root of the trouble (see man pthread_key_create):
"At thread exit, if a key value has a non-NULL destructor pointer,
and the thread has a non-NULL value associated with that key,
the value of the key is set to NULL, and then the function pointed to is called
with the previously associated value as its sole argument."

At thread exit we need to recover the thread-specific threadEntry
otherwise the subsequent calls of getThreadEntry may recreate it
(what actually DOES  happen in the test ThreadLocalPtr.CreateOnThreadExit)
and the newly created threadEntry will "leak". It will live longer than the corresponding
thread violating the internal invariant of StaticMeta and also it will break
the code of the method onThreadExit. In particular this bug causes the failure
of the test ThreadLocalPtr.CreateOnThreadExit on OSX.

Reviewed By: @lbrandy

Differential Revision: D2304950

folly/detail/ThreadLocalDetail.h

index bddb65604dc28019fc016d1a955ea06a32452005..c5fb61e4001cc664227a8adbe662e2f0167a656d 100644 (file)
@@ -267,6 +267,12 @@ struct StaticMeta {
     DCHECK_EQ(ptr, &meta);
     DCHECK_GT(threadEntry->elementsCapacity, 0);
 #else
+    // pthread sets the thread-specific value corresponding
+    // to meta.pthreadKey_ to NULL before calling onThreadExit.
+    // We need to set it back to ptr to enable the correct behaviour
+    // of the subsequent calls of getThreadEntry
+    // (which may happen in user-provided custom deleters)
+    pthread_setspecific(meta.pthreadKey_, ptr);
     ThreadEntry* threadEntry = static_cast<ThreadEntry*>(ptr);
 #endif
     {