WG 14 Document: N1751
Submitter: Aaron Ballman (US)
Submission Date: 2013-08-29
Source:
Reference Document:
Version: 1.0
Date: Aug 2013
Subject: thread-specific storage destructor invocation

Summary

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.

Suggested Change

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.
to
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. 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.
to
The 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.