diff options
| author | Eric Fiselier <eric@efcs.ca> | 2015-08-18 19:40:38 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2015-08-18 19:40:38 +0000 |
| commit | 4504cf2c8de1e6c2479e07c06b71e4506fe8fe70 (patch) | |
| tree | fe1a86b484575587cd2b332705a63e9e96c98f9d /libcxx/include/thread | |
| parent | 556f9340f75ab0300ec194d27e115be8a91d849e (diff) | |
| download | bcm5719-llvm-4504cf2c8de1e6c2479e07c06b71e4506fe8fe70.tar.gz bcm5719-llvm-4504cf2c8de1e6c2479e07c06b71e4506fe8fe70.zip | |
[libc++] Fix PR22606 - Leak pthread_key with static storage duration to ensure all of thread-local destructors are called.
Summary:
See https://llvm.org/bugs/show_bug.cgi?id=22606 for more discussion.
Most of the changes in this patch are file reorganization to help ensure assumptions about how __thread_specific_pointer is used hold. The assumptions are:
* `__thread_specific_ptr<Tp>` is only created with a `__thread_struct` pointer.
* `__thread_specific_ptr<Tp>` can only be constructed inside the `__thread_local_data()` function.
I'll remove the comments before committing. They are there for clarity during review.
Reviewers: earthdok, mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8802
llvm-svn: 245334
Diffstat (limited to 'libcxx/include/thread')
| -rw-r--r-- | libcxx/include/thread | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/libcxx/include/thread b/libcxx/include/thread index 8a30102f427..6be11337c21 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -113,11 +113,38 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time); _LIBCPP_BEGIN_NAMESPACE_STD +template <class _Tp> class __thread_specific_ptr; +class _LIBCPP_TYPE_VIS __thread_struct; +class _LIBCPP_HIDDEN __thread_struct_imp; +class __assoc_sub_state; + +_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); + +class _LIBCPP_TYPE_VIS __thread_struct +{ + __thread_struct_imp* __p_; + + __thread_struct(const __thread_struct&); + __thread_struct& operator=(const __thread_struct&); +public: + __thread_struct(); + ~__thread_struct(); + + void notify_all_at_thread_exit(condition_variable*, mutex*); + void __make_ready_at_thread_exit(__assoc_sub_state*); +}; + template <class _Tp> class __thread_specific_ptr { pthread_key_t __key_; + // Only __thread_local_data() may construct a __thread_specific_ptr + // and only with _Tp == __thread_struct. + static_assert(is_same<_Tp, __thread_struct>::value, ""); + __thread_specific_ptr(); + friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); + __thread_specific_ptr(const __thread_specific_ptr&); __thread_specific_ptr& operator=(const __thread_specific_ptr&); @@ -125,7 +152,6 @@ class __thread_specific_ptr public: typedef _Tp* pointer; - __thread_specific_ptr(); ~__thread_specific_ptr(); _LIBCPP_INLINE_VISIBILITY @@ -159,7 +185,10 @@ __thread_specific_ptr<_Tp>::__thread_specific_ptr() template <class _Tp> __thread_specific_ptr<_Tp>::~__thread_specific_ptr() { - pthread_key_delete(__key_); + // __thread_specific_ptr is only created with a static storage duration + // so this destructor is only invoked during program termination. Invoking + // pthread_key_delete(__key_) may prevent other threads from deleting their + // thread local data. For this reason we leak the key. } template <class _Tp> @@ -307,26 +336,6 @@ public: static unsigned hardware_concurrency() _NOEXCEPT; }; -class __assoc_sub_state; - -class _LIBCPP_HIDDEN __thread_struct_imp; - -class _LIBCPP_TYPE_VIS __thread_struct -{ - __thread_struct_imp* __p_; - - __thread_struct(const __thread_struct&); - __thread_struct& operator=(const __thread_struct&); -public: - __thread_struct(); - ~__thread_struct(); - - void notify_all_at_thread_exit(condition_variable*, mutex*); - void __make_ready_at_thread_exit(__assoc_sub_state*); -}; - -_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); - #ifndef _LIBCPP_HAS_NO_VARIADICS template <class _Fp, class ..._Args, size_t ..._Indices> |

