Subject: [boost] [thread] thread_specific_ptr, dangerous conflation of identity and address
From: Edd Dawson (lists_at_[hidden])
Date: 2010-02-15 17:39:22
A thread_specific_ptr appears to use its own address as a key. For example, the
two tss objects created below will likely share the same key:
When thread_specific_ptr's destructor is called, it does a reset() which clears
the data for the thread doing the destruction. However, data for other threads
still remain. I find this asymmetric behaviour a little strange. Why should all
threads but one see their old data?
The bigger problem though, is that it might not be *their* old data. It can just
as easily be someone else's old data due to coincidental alignment of different
thread_specific_ptrs on the stack at entirely unrelated points in the program,
or even in different libraries that each happen to use boost::thread_specific_ptr!
It's easy to see the problem here as the calls are very close to one another. In
general, however, this strikes me as being really rather dangerous behaviour.
Would it be fair to call it a bug? It seems it is only safe to allocate
thread_specific_ptrs in static storage.
A complete example is listed at the end. It exhibits the kind of behaviour I'm
talking about on my x86 systems, at least.
//#define BOOST_ALL_NO_LIB 1
using namespace boost;
typedef function<void ()> task_type;
// Simple multi-producer-single-consumer job queue.
// Manages its own consumer thread.
void add(const task_type &task)
dying_ = true;
bool wait_for_task(task_type &task)
while (!dying_ && tasks_.empty())
if (dying_) return false;
task = tasks_.front();
void access_tsp(thread_specific_ptr<T> &tsp, barrier &b)
std::cout << "Already initialized to " << *tsp << "!\n";
void f(jobq &q)
q.add(bind(&access_tsp<T>, ref(tsp), ref(b)));
b.wait(); // wait until it's safe to destroy tsp
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk