2

In thread pool, threads are reused to avoid thread creation and destruction. When the thread pool reuses a thread, it does not clear the data in thread local storage. Hence, when a method examines thread local storage, the values it finds are left over from an earlier use of the thread pool thread.

Function local variables are local to function and not to threads. But when i created a thread pool using boost::asio::thread_pool, the memory for local variables created inside function share the same memory for the same thread.

Hence, I have few questions...

  1. Are function local variables stored inside thread local storage. And is it because of that i am getting same memory for the same threads?
  2. The same question for function parameters which are passed by value ?
  3. Is there any way to clear the thread local storage before reusing the threads?

Program

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/asio/thread_pool.hpp>
#include <BoostThreading/UtilBoost.hpp>
#include <iostream>
boost::mutex mutex;
void my_task(int g)
{
    boost::lock_guard<boost::mutex> lock(mutex);
    int i=0;
    i++;
    std::cout<<boost::this_thread::get_id()<<" "<<&i<<" "<<i<<" "<<&g<<" "<<g<<"\n";
    SleepMs(30);
}
int main()
{
    boost::asio::thread_pool pool(4);
    for(int i=0;i<10;i++)
        boost::asio::post(pool, boost::bind(my_task,i));
    pool.join();
}

Output Output image here

First is the thread id, second is the address for variable i created inside the function and third address is the address for variable g passed to my_task by pass by value.

Tharani B
  • 21
  • 3

1 Answers1

1
  1. Are function local variables stored inside thread local storage. And is it because of that i am getting same memory for the same threads?

Function local variables live on the stack.

The stack is defacto always (implicitly) thread-local. That's a direct result of CPU design.

Only exceptions might be when context switching libraries such as Boost Context (e.g. implementing stackful coroutines or fibers).

Read this absolutely awesome answer to understand stack allocation and stack reuse: Can a local variable's memory be accessed outside its scope?

  1. The same question for function parameters which are passed by value ?

Same answer.

  1. Is there any way to clear the thread local storage before reusing the threads?

That's actually an interesting question. It generalizes to "is there a secure-erase allocator in C++ that includes objects with automatic storage duration?".

No that doesn't exist. It can be approximated, but it will involve wrapping all your primitive types into non-trivial types. It may be more effective to actively wipe the stack down with an explicit function at the end of a task.

The upper frames will have to remain in-tact because they may (and will) contain information required for proper thread management (e.g. if you use boost::thread it will contain the structures that allow thread interruption, portable emulation of thread-local storage with boost::thread_specific_ptr etc.)

If you need anything like this, look for an existing library around "secure erase" because it's very very easy to get wrong. E.g. a naive memset call can (and will) often be optimized away by the compiler.

sehe
  • 374,641
  • 47
  • 450
  • 633