SanitizerCommon.PthreadDestructorIterations currently FAILs on Solaris:
[ RUN ] SanitizerCommon.PthreadDestructorIterations
/vol/llvm/src/compiler-rt/local/lib/sanitizer_common/tests/sanitizer_posix_test.cc:58: Failure
Value of: destructor_executed
Actual: true
Expected: false
[ FAILED ] SanitizerCommon.PthreadDestructorIterations (1 ms)
It turns out that destructor is called 4 times after the first call to SpawnThread, but
5 times after the second. While PTHREAD_DESTRUCTOR_ITERATIONS is 4 in
<limits.h>, the Solaris pthread_key_create(3C) man page documents
If, after all the destructors have been called for all keys with non-
null values, there are still some keys with non-null values, the
process will be repeated. POSIX requires that this process be executed
at least PTHREAD_DESTRUCTOR_ITERATIONS times. Solaris calls the
destructors repeatedly until all values with associated destructors are
NULL. Destructors that set new values can cause an infinite loop.
The patch adjusts the test case to allow for this.
Tested on x86_64-pc-solaris2.11.
Differential Revision: https://reviews.llvm.org/D65055
llvm-svn: 367705
86 lines
2.7 KiB
C++
86 lines
2.7 KiB
C++
//===-- sanitizer_posix_test.cpp ------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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 <pthread.h>
|
|
#include <sys/mman.h>
|
|
|
|
namespace __sanitizer {
|
|
|
|
static pthread_key_t key;
|
|
static bool destructor_executed;
|
|
|
|
extern "C"
|
|
void destructor(void *arg) {
|
|
uptr iter = reinterpret_cast<uptr>(arg);
|
|
if (iter > 1) {
|
|
ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast<void *>(iter - 1)));
|
|
return;
|
|
}
|
|
destructor_executed = true;
|
|
}
|
|
|
|
extern "C"
|
|
void *thread_func(void *arg) {
|
|
return reinterpret_cast<void*>(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<void *>(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(GetPthreadDestructorIterations());
|
|
EXPECT_TRUE(destructor_executed);
|
|
SpawnThread(GetPthreadDestructorIterations() + 1);
|
|
#if SANITIZER_SOLARIS
|
|
// Solaris continues calling destructors beyond PTHREAD_DESTRUCTOR_ITERATIONS.
|
|
EXPECT_TRUE(destructor_executed);
|
|
#else
|
|
EXPECT_FALSE(destructor_executed);
|
|
#endif
|
|
ASSERT_EQ(0, pthread_key_delete(key));
|
|
}
|
|
|
|
TEST(SanitizerCommon, IsAccessibleMemoryRange) {
|
|
const int page_size = GetPageSize();
|
|
uptr mem = (uptr)mmap(0, 3 * page_size, PROT_READ | PROT_WRITE,
|
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
// Protect the middle page.
|
|
mprotect((void *)(mem + page_size), page_size, PROT_NONE);
|
|
EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size - 1));
|
|
EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size));
|
|
EXPECT_FALSE(IsAccessibleMemoryRange(mem, page_size + 1));
|
|
EXPECT_TRUE(IsAccessibleMemoryRange(mem + page_size - 1, 1));
|
|
EXPECT_FALSE(IsAccessibleMemoryRange(mem + page_size - 1, 2));
|
|
EXPECT_FALSE(IsAccessibleMemoryRange(mem + 2 * page_size - 1, 1));
|
|
EXPECT_TRUE(IsAccessibleMemoryRange(mem + 2 * page_size, page_size));
|
|
EXPECT_FALSE(IsAccessibleMemoryRange(mem, 3 * page_size));
|
|
EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2));
|
|
}
|
|
|
|
} // namespace __sanitizer
|
|
|
|
#endif // SANITIZER_POSIX
|