[Boost-bugs] [Boost C++ Libraries] #2797: Two problems with thread_specific_ptr

Subject: [Boost-bugs] [Boost C++ Libraries] #2797: Two problems with thread_specific_ptr
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2009-02-24 16:50:14

#2797: Two problems with thread_specific_ptr
 Reporter: hkhalfal_at_[hidden] | Owner: anthonyw
     Type: Bugs | Status: new
Milestone: Boost 1.39.0 | Component: thread
  Version: Boost 1.38.0 | Severity: Showstopper
 Keywords: thread_specific_ptr; crash; leak |
 This note describes two problems with thread_specific_ptr that we have
 discovered and proposes solutions to both of them:

 1) A crash at shutdown occurs when thread_specific_ptr is used from
 a dll and the dll gets unloaded before the thread shutdown cleanup code
 for thread local storage takes place.
 2) A subtle leak in the implementation of thread_specific_ptr.

 Analysis of the first problem

 A thread_specific_ptr object has different thread specific “data” in
 different threads (this is what is returned by the get() function). The
 thread specific data gets destructed and removed from their thread
 specific store at thread shutdown (the latter is implemented as a linked
 list of nodes each holding a pointer to the thread specific data and a
 pointer to a cleanup function). However, the thread where the
 thread_specic_ptr object was constructed must destruct its thread specific
 data and remove it from the store long before thread shutdown. It must do
 it when the thread_specific_ptr object is destructed. The implementation
 in tss.hpp attempts to do this by calling reset() with a nil argument in
 the destructor of the thread_specific_ptr template class.

 Unfortunately, because this does not remove the entry from the linked list
 of thread specifics, and because it does not clear the cleanup pointer for
 that entry, it is possible to get a crash if the dll where the
 thread_specific_ptr was constructed gets unloaded before the thread
 shutdown cleanup code occurs. This can happen because the thread shutdown
 cleanup code calls the delete function of each node in the linked list
 even if the data in the node (the pointer to thread local data itself) is
 nil. The call to the delete function leads to a crash because the dll
 where the function pointer was defined has been unloaded.

 Proposed solution for first problem

 To avoid this issue, thread_specific_ptr should be clearing the cleanup
 pointer on destruction. Another solution is for thread_specific_ptr to
 remove the node from the linked list on destruction.

 Furthermore, in the definition of thread_specific_ptr, we should expect
 consistent behavior with release and reset with a nil argument. Currently,
 release clears the cleanup function pointer but reset with a nil argument
 does not. We expect they both be consistent, one way or another.

 Analysis of the second problem

 Because thread_specific_ptr does not remove the node from the tss linked
 list at destruction, we have a problem. The size of the linked list can
 become very large depending on the usage pattern of thread_specific_ptr.
 If the program creates and destructs thread_specific_ptr repetitively this
 may lead to major increase in the size of the linked list.

 A possible scenario where this can occur is if objects of class A are
 shared across threads, and if we keep creating and destructing them
 repetitively during execution. It is conceivable that the programmer need
 to store thread specific information in class A:

 Class A

 thread_specific_ptr ts_ptr;

 If the program creates and destructs objects of class A repetitively this
 will lead to a leak as nodes get added to the cleanup list but never
 removed until thread shutdown. It is conceivable that the executable run
 out of memory because of this.

 Proposed solution for second problem:

 thread_specific_ptr must remove the node from the linked list on



Ticket URL: <https://svn.boost.org/trac/boost/ticket/2797>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:59 UTC