[libc] TLS cleanup does not handle requeuing properly
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
This is also found during libc++ bringing up process. Libc currently only scan the dtor list once without clearing the key. This leads to the following crash:
- PR30202_notify_from_pthread_created_thread
- notify_all_at_thread_exit_lwg3343
TLS tearning down should clear the key before dtor call and handle potentially requeued TLS dtor up to `PTHREAD_DESTRUCTOR_ITERATIONS` number of times, similar to the following:
```c++
void call_atexit_callbacks(ThreadAttributes *attrib) {
attrib->atexit_callback_mgr->call();
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS;
++iteration) {
for (size_t i = 0; i < TSS_KEY_COUNT; ++i) {
TSSValueUnit &unit = tss_values[i];
if (unit.dtor == nullptr || unit.payload == nullptr)
continue;
// POSIX requires the implementation to clear the key's value before
// invoking the destructor. A destructor may publish a new non-null value
// with pthread_setspecific(), in which case the implementation must scan
// the keys again, up to PTHREAD_DESTRUCTOR_ITERATIONS times.
void *payload = unit.payload;
unit.payload = nullptr;
unit.dtor(payload);
}
bool has_pending_tss_dtor = false;
for (size_t i = 0; i < TSS_KEY_COUNT; ++i) {
TSSValueUnit &unit = tss_values[i];
if (unit.dtor != nullptr && unit.payload != nullptr) {
has_pending_tss_dtor = true;
break;
}
}
if (!has_pending_tss_dtor)
break;
}
}
```
Contributor guide
Assessment
This issue has not been assessed yet.