llvm / llvm/llvm-project

[libc] TLS cleanup does not handle requeuing properly

Open
#194,029 1 comment 0 reactions 0 assignees View on GitHub
libc
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.