As per pthread_key_create man page we can associate a destructor to be called at thread shut down. My problem is that the destructor function I have registered is not being called. Gist of my code is as follows.
static pthread_key_t key;
static pthread_once_t tls_init_flag = PTHREAD_ONCE_INIT;
void destructor(void *t) {
// thread local data structure clean up code here, which is not getting called
}
void create_key() {
pthread_key_create(&key, destructor);
}
// This will be called from every thread
void set_thread_specific() {
ts = new ts_stack; // Thread local data structure
pthread_once(&tls_init_flag, create_key);
pthread_setspecific(key, ts);
}
Any idea what might prevent this destructor being called? I am also using atexit() at moment to do some cleanup in the main thread. Is there any chance that is interfering with destructor function being called? I tried removing that as well. Still didn't work though. Also I am not clear if I should handle the main thread as a separate case with atexit. (It's a must to use atexit by the way, since I need to do some application specific cleanup at application exit)
This is by design.
The main thread exits (by returning or calling
exit()
), and that doesn't usepthread_exit()
. POSIX documentspthread_exit
calling the thread-specific destructors.You could add
pthread_exit()
at the end ofmain
. Alternatively, you can useatexit
to do your destruction. In that case, it would be clean to set the thread-specific value toNULL
so in case thepthread_exit
was invoked, the destruction wouldn't happen twice for that key.UPDATE Actually, I've solved my immediate worries by simply adding this to my global unit test setup function:
So, in context of my global fixture class
MyConfig
:Some of the references used:
PS. Of course c++11 introduced
<thread>
so you have better and more portable primitves to work with.I wrote a quick test and the only thing I changed was moving the
create_key
call of yours outside of theset_thread_specific
.That is, I called it within the main thread.
I then saw my destroy get called when the thread routine exited.
I call destructor() manually at the end of main():
Of course key should be properly initialized earlier in main() code. PS. Calling Pthread_Exit() at the end to main() seems to hang entire application...
Your initial thought of handling the main thread as a separate case with atexit worked best for me.
Be ware that pthread_exit(0) overwrites the exit value of the process. For example, the following program will exit with status of zero even though main() returns with number three:
It's already in sehe's answer, just to present the key points in a compact way:
pthread_key_create()
destructor calls are triggered by a call topthread_exit()
.pthread_exit()
was called (i. e., destructor calls are triggered).main()
returns, the behaviour is as ifexit()
was called — no destructor calls are triggered.This is explained in http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html. See also C++17 6.6.1p5 or C11 5.1.2.2.3p1.
I had similar issue as yours:
pthread_setspecific
sets a key, but the destructor never gets called. To fix it we simply switched tothread_local
in C++. You could also do something like if that change is too complicated:For example, assume you have some class
ThreadData
that you want some action to be done on when the thread finishes execution. You define the destructor something on these lines:When your thread starts, you allocate memory for
ThreadData*
instance and assign a destructor to it like this:Notice that
ThreadLocalDestructor
is defined as thread_local. We rely on C++11 mechanism that when the thread exits, the destructor ofThreadLocalDestructor
will be automatically called, and~ThreadLocalDestructor
is implemented to call functiondestroy_my_data
.Here is the implementation of ThreadLocalDestructor: