
Michael Glassford wrote: [...]
Most of the quotes apply to thread termination cleanup handlers, not tss cleanup handlers or whatever you call them,
Official name is thread-specific data destructors or simply destructors.
but perhaps the same principles apply?
Yep.
If so, the executive summary is that I was wrong, and the order is specified?
If you call exit() either explicitly or by means of returning from main() than no cleanup (pthread_cleanup_push()) handlers or TSD destructors are called. Now, http://www.opengroup.org/onlinepubs/009695399/functions/pthread_exit.html says "After all cancellation cleanup handlers have been executed, if the thread has any thread-specific data, appropriate destructor functions shall be called in an unspecified order. ... The process shall exit with an exit status of 0 after the last thread has been terminated. The behavior shall be as if the implementation called exit() with a zero argument at thread termination time." #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <pthread.h> void atexit_func() { printf("atexit_func()\n"); } void tsd_dtor(void * value) { printf("tsd_dtor(%p)\n", value); } void f() { static struct object { ~object() { printf("~object()\n"); } } o; } pthread_key_t key; int main() { int status; f(); status = atexit(&atexit_func); assert(!status); status = pthread_key_create(&key, &tsd_dtor); assert(!status); status = pthread_setspecific(key, &key); assert(!status); pthread_exit(0); } shall print "atexit_func()" after "tsd_dtor" and before "~object()". And you better do NOT mess with threading stuff in atexit handlers and/or C++ destructors of objects with static storage duration. ;-) regards, alexander.