[libc-commits] [PATCH] D148291: [LIBC] Fix incorrect behavior with pthread_key_t when value was nullptr

Noah Goldstein via Phabricator via libc-commits libc-commits at lists.llvm.org
Wed Apr 19 17:55:17 PDT 2023


This revision was automatically updated to reflect the committed changes.
Closed by commit rG6f1a9ed072de: [LIBC] Fix incorrect behavior with pthread_key_t when value was nullptr (authored by goldstein.w.n).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D148291/new/

https://reviews.llvm.org/D148291

Files:
  libc/src/__support/threads/thread.cpp
  libc/test/integration/src/pthread/pthread_tss_test.cpp


Index: libc/test/integration/src/pthread/pthread_tss_test.cpp
===================================================================
--- libc/test/integration/src/pthread/pthread_tss_test.cpp
+++ libc/test/integration/src/pthread/pthread_tss_test.cpp
@@ -21,16 +21,19 @@
 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<int *>(data);
   *v = THREAD_DATA_FINIVAL;
 }
 
-void *func(void *obj) {
+// Used to test that we don't call the destructor when the mapped value in NULL.
+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<int *>(__llvm_libc::pthread_getspecific(key));
   ASSERT_TRUE(d != nullptr);
@@ -40,7 +43,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<int *>(__llvm_libc::pthread_getspecific(key));
@@ -56,7 +66,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;
 }
Index: libc/src/__support/threads/thread.cpp
===================================================================
--- libc/src/__support/threads/thread.cpp
+++ libc/src/__support/threads/thread.cpp
@@ -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);
   }
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D148291.515158.patch
Type: text/x-patch
Size: 2816 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20230420/4695e369/attachment.bin>


More information about the libc-commits mailing list