The standard specifies that tss_delete() releases any
resources used by the thread-specific storage identified by
key. However, it does not state whether the
destructor, if one was specified for that key, will or
will not be called. It would be reasonable for a programmer to
believe tss_delete() will execute the destructor.
However, a narrow reading of the standard implies that this is
dangerous. Because tss_delete() does not specify
whether the key is removed or not from the internal
list of thread-specific keys, it is plausible that the
destructor for the key will be fired a second time
when the thread is terminated, leading to double frees. For
example:
void dtor(void *data) {
free(data); // Double free?
}
int thread_func(void *arg) {
tss_t key;
if (thrd_success == tss_create(&key, dtor)) {
tss_set(key, malloc(4));
tss_delete(key); // Could call dtor
}
return 0; // Could call dtor
}
The standard should be more specific about what
points the thread-specific storage destructor will be called.
At 7.26.6.1p3, change:If the tss_create function is successful, it sets the thread-specific storage pointed to by key to a value that uniquely identifies the newly created pointer and returns thrd_success; otherwise, thrd_error is returned and the thread-specific storage pointed to by key is set to an undefined value.toIf the tss_create function is successful, it sets the thread-specific storage pointed to by key to a value that uniquely identifies the newly created pointer and returns thrd_success. If a non-null destructor was specified, it will be called when the thread terminates provided the key was not deleted via tss_delete. If thrd_error is returned, the thread-specific storage pointed to by key is set to an undefined value.At 7.26.6.2p2, change:The tss_delete function releases any resources used by the thread-specific storage identified by key.toThe tss_delete function releases any resources used by the thread-specific storage identified by key. If a non-null destructor was specified for the key, it will be called. The key is removed from the thread-specific storage.