From pthread_key_create manpage:
An optional destructor function may be associated with each key value. To the output of a stream, if the key value has a non-NULL pointer to the destructor and thread has a value other than NULL with the key, a function pointing to is called with the current associated value as the only argument. the order of the calls to the destructor is not specified if more than one calls for a destructor for the stream when it exits.
If, in the end, the destructors are called for all non-NULL values ββwith the corresponding destructors, there are still some non-NULL values ββfrom the associated destructors, then the process repeats. If after least [PTHREAD_DESTRUCTOR_ITERATIONS] the destructor iterations require outstanding values ββother than NULL, there are still some non-NULL values ββfrom the associated destructors, the implementation stops calling destructors.
I wrote a small example with a simple destructive print of "Hello World" for a value other than NULL. As far as I can see, this destructor is called only once (at least in linux fedora and mac os x), even if the value of a specific thread is still not NULL after the first call to the destructor.
Did I miss something?! (PTHREAD_DESTRUCTOR_ITERATIONS = 4 on glibc.)
Here is my little example:
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #define NB_THREADS 1 #define NB_KEYS 1 static pthread_key_t keys[NB_KEYS]; static pthread_mutex_t mutex; void destruction (void *arg) { (int) arg ++; printf ("Destructor called! -- key value : %i\n", (int)arg); } void* startup_routine(void* argv) { int i; int th = (int) argv; for (i = 0; i < NB_KEYS; i++) pthread_setspecific(keys[i], (void*) ((th + i)* 2)); pthread_mutex_lock(&mutex); printf("Thread %i\n", th); for (i = 0; i < NB_KEYS; i++) printf ("\tkeys[%i] : %i\n", i, (int)pthread_getspecific(keys[i])); pthread_mutex_unlock(&mutex); return "End"; } int main(int argc, char** argv) { int i; void *result; pthread_t thread[NB_THREADS]; for (i = 0; i < NB_KEYS; i++) pthread_key_create(&keys[i], destruction); pthread_mutex_init(&mutex, NULL); for (i = 0; i < NB_THREADS; i++) pthread_create( &thread[i], NULL, startup_routine, (void*)(i+1) ); for (i = 0; i < NB_THREADS; i++) { pthread_join( thread[i], &result ); printf("Return from the thread %i = '%s'\n", i, (char*)result ); } return 0; }