|
Message-ID: <87eeu85jej.fsf@oldenburg2.str.redhat.com> Date: Wed, 04 Mar 2020 14:39:16 +0100 From: Florian Weimer <fweimer@...hat.com> To: libc-coord@...ts.openwall.com Subject: Destructors for (ELF) TLS variables POSIX supports destructors for its per-thread data support. The behavior is slightly different from what has been standardized for C++ thread_local variables with destructors: | If, after all the destructors have been called for all non-NULL values | with associated destructors, there are still some non-NULL values with | associated destructors, then the process is repeated. If, after at | least {PTHREAD_DESTRUCTOR_ITERATIONS} iterations of destructor calls | for outstanding non-NULL values, there are still some non-NULL values | with associated destructors, implementations may stop calling | destructors, or they may continue calling destructors until no | non-NULL values with associated destructors exist, even though this | might result in an infinite loop. This iteration behavior might look like a crass hack, but I think it is actually a fairly reasonable way to deal with the destruction problem for singletons. (If I recall correctly, Andrei Alexandrescu discusses the surrounding issues extensively in Modern C++ Design, in the context of general, non-thread-specific singletons, which face exactly the same problem on process termination.) In the GNU toolchain, we currently do not have support for TLS destructors, and the C++ support we have slightly broken (it crashes on out-of-memory conditions). I wonder if it would make sense to define something analogous to DT_FINI_ARRAY, but for destructors that are called on thread exit. Has anyone implemented something like that? It does not look too hard to do. The required changes should be largely mechanical (new ELF section header type etc.). Would it make sense to mirror the POSIX iteration behavior? We probably cannot check if the relevant TLS variables are zero, so we'd likely have to rely on a return value from the destructor to indicate if it has performed any actions that might have resurrected further thread-local state. Integration with dlclose is another open question. It's possible to do nothing special here and leak resources (because the destructors for running threads cannot be called once their code is gone). If that's not feasible for some DSOs, they would have to register the thread-local state with the DSO and perform the dealloction (with proper synchronization) from the DSO's destructor. Or they can specify NODELETE to prevent unloading. I'm thinking about this because we are considering the removalof deferred resource allocation for ELF TLS variables. If we ever do that, memory would be allocated on thread creation or during dlopen, and not on first access to the variable. But it would mean that libraries may want to add an indirection if they need large, occasionally used per-thread data. But then they need some sort of destructor to deallocate that storage. (The main advantage of ELF TLS over pthread_key_create etc. is better integration with tools like debuggers, and increased type safety at the language layer.) Thanks, Florian
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.