Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -440,6 +440,12 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules, string_predicate_t filter); +#if SANITIZER_POSIX +const uptr kPthreadDestructorIterations = 4; +#else +// Unused on Windows. +const uptr kPthreadDestructorIterations = 0; +#endif } // namespace __sanitizer #endif // SANITIZER_COMMON_H Index: lib/sanitizer_common/sanitizer_linux.h =================================================================== --- lib/sanitizer_common/sanitizer_linux.h +++ lib/sanitizer_common/sanitizer_linux.h @@ -76,9 +76,6 @@ // Call cb for each region mapped by map. void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); - -// PTHREAD_DESTRUCTOR_ITERATIONS from glibc. -const uptr kPthreadDestructorIterations = 4; } // namespace __sanitizer #endif // SANITIZER_LINUX Index: lib/sanitizer_common/sanitizer_platform_limits_posix.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -15,6 +15,7 @@ #ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H #define SANITIZER_PLATFORM_LIMITS_POSIX_H +#include "sanitizer_internal_defs.h" #include "sanitizer_platform.h" namespace __sanitizer { @@ -821,6 +822,7 @@ extern unsigned IOCTL_TIOCSERSETMULTI; extern unsigned IOCTL_TIOCSSERIAL; #endif + } // namespace __sanitizer #endif Index: lib/sanitizer_common/tests/CMakeLists.txt =================================================================== --- lib/sanitizer_common/tests/CMakeLists.txt +++ lib/sanitizer_common/tests/CMakeLists.txt @@ -11,6 +11,7 @@ sanitizer_list_test.cc sanitizer_mutex_test.cc sanitizer_nolibc_test.cc + sanitizer_posix_test.cc sanitizer_printf_test.cc sanitizer_scanf_interceptor_test.cc sanitizer_stackdepot_test.cc Index: lib/sanitizer_common/tests/sanitizer_linux_test.cc =================================================================== --- lib/sanitizer_common/tests/sanitizer_linux_test.cc +++ lib/sanitizer_common/tests/sanitizer_linux_test.cc @@ -255,42 +255,6 @@ } } -static pthread_key_t key; -static bool destructor_executed; - -extern "C" -void destructor(void *arg) { - uptr iter = reinterpret_cast(arg); - if (iter > 1) { - ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast(iter - 1))); - return; - } - destructor_executed = true; -} - -extern "C" -void *thread_func(void *arg) { - return reinterpret_cast(pthread_setspecific(key, arg)); -} - -static void SpawnThread(uptr iteration) { - destructor_executed = false; - pthread_t tid; - ASSERT_EQ(0, pthread_create(&tid, 0, &thread_func, - reinterpret_cast(iteration))); - void *retval; - ASSERT_EQ(0, pthread_join(tid, &retval)); - ASSERT_EQ(0, retval); -} - -TEST(SanitizerCommon, PthreadDestructorIterations) { - ASSERT_EQ(0, pthread_key_create(&key, &destructor)); - SpawnThread(kPthreadDestructorIterations); - EXPECT_TRUE(destructor_executed); - SpawnThread(kPthreadDestructorIterations + 1); - EXPECT_FALSE(destructor_executed); -} - } // namespace __sanitizer #endif // SANITIZER_LINUX Index: lib/sanitizer_common/tests/sanitizer_posix_test.cc =================================================================== --- /dev/null +++ lib/sanitizer_common/tests/sanitizer_posix_test.cc @@ -0,0 +1,62 @@ +//===-- sanitizer_posix_test.cc -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tests for POSIX-specific code. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_POSIX + +#include "sanitizer_common/sanitizer_common.h" +#include "gtest/gtest.h" + +#include + +namespace __sanitizer { + +static pthread_key_t key; +static bool destructor_executed; + +extern "C" +void destructor(void *arg) { + uptr iter = reinterpret_cast(arg); + if (iter > 1) { + ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast(iter - 1))); + return; + } + destructor_executed = true; +} + +extern "C" +void *thread_func(void *arg) { + return reinterpret_cast(pthread_setspecific(key, arg)); +} + +static void SpawnThread(uptr iteration) { + destructor_executed = false; + pthread_t tid; + ASSERT_EQ(0, pthread_create(&tid, 0, &thread_func, + reinterpret_cast(iteration))); + void *retval; + ASSERT_EQ(0, pthread_join(tid, &retval)); + ASSERT_EQ(0, retval); +} + +TEST(SanitizerCommon, PthreadDestructorIterations) { + ASSERT_EQ(0, pthread_key_create(&key, &destructor)); + SpawnThread(kPthreadDestructorIterations); + EXPECT_TRUE(destructor_executed); + SpawnThread(kPthreadDestructorIterations + 1); + EXPECT_FALSE(destructor_executed); +} + +} // namespace __sanitizer + +#endif // SANITIZER_POSIX