diff --git a/libc/src/__support/threads/thread.cpp b/libc/src/__support/threads/thread.cpp --- a/libc/src/__support/threads/thread.cpp +++ b/libc/src/__support/threads/thread.cpp @@ -87,7 +87,7 @@ } }; -TSSKeyMgr tss_key_mgr; +static TSSKeyMgr tss_key_mgr; struct TSSValueUnit { bool active = false; @@ -151,7 +151,8 @@ attrib->atexit_callback_mgr->call(); for (size_t i = 0; i < TSS_KEY_COUNT; ++i) { TSSValueUnit &unit = tss_values[i]; - if (unit.dtor != nullptr) + // Both dtor and value need to nonnull to call dtor + if (unit.dtor != nullptr && unit.payload != nullptr) unit.dtor(unit.payload); } } diff --git a/libc/test/integration/src/pthread/pthread_tss_test.cpp b/libc/test/integration/src/pthread/pthread_tss_test.cpp --- a/libc/test/integration/src/pthread/pthread_tss_test.cpp +++ b/libc/test/integration/src/pthread/pthread_tss_test.cpp @@ -21,16 +21,18 @@ static constexpr int THREAD_DATA_FINIVAL = 0x4321; static constexpr int THREAD_RUN_VAL = 0x600D; -int child_thread_data = THREAD_DATA_INITVAL; -int main_thread_data = THREAD_DATA_INITVAL; +static int child_thread_data = THREAD_DATA_INITVAL; +static int main_thread_data = THREAD_DATA_INITVAL; -pthread_key_t key; -void dtor(void *data) { +static pthread_key_t key; +static void dtor(void *data) { auto *v = reinterpret_cast(data); *v = THREAD_DATA_FINIVAL; } -void *func(void *obj) { +static void dtor_failure(void *) { ASSERT_TRUE(false); } + +static void *func(void *obj) { ASSERT_EQ(__llvm_libc::pthread_setspecific(key, &child_thread_data), 0); int *d = reinterpret_cast(__llvm_libc::pthread_getspecific(key)); ASSERT_TRUE(d != nullptr); @@ -40,7 +42,14 @@ return nullptr; } -TEST_MAIN() { +static void *func_null_val(void *) { + // null value, we should not call dtor + ASSERT_EQ(__llvm_libc::pthread_setspecific(key, nullptr), 0); + ASSERT_EQ(__llvm_libc::pthread_getspecific(key), nullptr); + return nullptr; +} + +static void standard_usage_test() { ASSERT_EQ(__llvm_libc::pthread_key_create(&key, &dtor), 0); ASSERT_EQ(__llvm_libc::pthread_setspecific(key, &main_thread_data), 0); int *d = reinterpret_cast(__llvm_libc::pthread_getspecific(key)); @@ -56,7 +65,20 @@ ASSERT_EQ(retval, nullptr); ASSERT_EQ(arg, THREAD_RUN_VAL); ASSERT_EQ(child_thread_data, THREAD_DATA_FINIVAL); + ASSERT_EQ(__llvm_libc::pthread_key_delete(key), 0); +} +static void null_value_test() { + pthread_t th; + ASSERT_EQ(__llvm_libc::pthread_key_create(&key, &dtor_failure), 0); + ASSERT_EQ(__llvm_libc::pthread_create(&th, nullptr, &func_null_val, nullptr), + 0); + ASSERT_EQ(__llvm_libc::pthread_join(th, nullptr), 0); ASSERT_EQ(__llvm_libc::pthread_key_delete(key), 0); +} + +TEST_MAIN() { + standard_usage_test(); + null_value_test(); return 0; }