C: pthread dataspecific destructor called only once

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; } 
+4
source share
2 answers

It seems that there are not many people who use pthread!

So, again, I will answer my question:

The destructor will be called more than once ONLY if pthread_setspecific is called in the destructor, changing the key value.

This is because, before calling the destructor, the key pointer is null, and the pointer is passed to the destructor. Therefore, if we want the key pointer to not be null, we just need to remember pthread_setspecific in it.

+3
source

I do not understand this secret. You have only 1 stream-related key and only 1 stream that defines the data related to the stream. Therefore, the destructor should be executed only once, as expected.

If you specify thread related data somewhere after pthread_create () in main (), the destructor will be called twice - once for the child thread and once for the thread associated with main ().

-1
source

All Articles