sanitizer_linux_test.cc revision 6eb836f9bd2b96a321ddc7fb5ea08aa65131e61f
19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===-- sanitizer_linux_test.cc -------------------------------------------===// 29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// The LLVM Compiler Infrastructure 49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// This file is distributed under the University of Illinois Open Source 69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// License. See LICENSE.TXT for details. 79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===// 99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Tests for sanitizer_linux.h 119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===// 139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "sanitizer_common/sanitizer_platform.h" 159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#if SANITIZER_LINUX 169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "sanitizer_common/sanitizer_linux.h" 189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "sanitizer_common/sanitizer_common.h" 209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "gtest/gtest.h" 219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include <pthread.h> 239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include <sched.h> 249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include <stdlib.h> 259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include <algorithm> 279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include <vector> 289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonnamespace __sanitizer { 309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonstruct TidReporterArgument { 329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson TidReporterArgument() { 339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_init(&terminate_thread_mutex, NULL); 349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_init(&tid_reported_mutex, NULL); 359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_init(&terminate_thread_cond, NULL); 369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_init(&tid_reported_cond, NULL); 379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson terminate_thread = false; 389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ~TidReporterArgument() { 419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_destroy(&terminate_thread_mutex); 429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_destroy(&tid_reported_mutex); 439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_destroy(&terminate_thread_cond); 449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_destroy(&tid_reported_cond); 459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pid_t reported_tid; 489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // For signaling to spawned threads that they should terminate. 499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_t terminate_thread_cond; 509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_t terminate_thread_mutex; 519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson bool terminate_thread; 529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // For signaling to main thread that a child thread has reported its tid. 539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_t tid_reported_cond; 549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_t tid_reported_mutex; 559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private: 579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Disallow evil constructors 589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson TidReporterArgument(const TidReporterArgument &); 599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson void operator=(const TidReporterArgument &); 609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}; 619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonclass ThreadListerTest : public ::testing::Test { 639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson protected: 649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson virtual void SetUp() { 659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_t pthread_id; 669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pid_t tid; 679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (uptr i = 0; i < kThreadCount; i++) { 689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson SpawnTidReporter(&pthread_id, &tid); 699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_ids_.push_back(pthread_id); 709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson tids_.push_back(tid); 719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson virtual void TearDown() { 759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_lock(&thread_arg.terminate_thread_mutex); 769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson thread_arg.terminate_thread = true; 779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_broadcast(&thread_arg.terminate_thread_cond); 789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_unlock(&thread_arg.terminate_thread_mutex); 799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (uptr i = 0; i < pthread_ids_.size(); i++) 809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_join(pthread_ids_[i], NULL); 819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson void SpawnTidReporter(pthread_t *pthread_id, pid_t *tid); 849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson static const uptr kThreadCount = 20; 869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::vector<pthread_t> pthread_ids_; 889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::vector<pid_t> tids_; 899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson TidReporterArgument thread_arg; 919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}; 929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Writes its TID once to reported_tid and waits until signaled to terminate. 949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid *TidReporterThread(void *argument) { 959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson TidReporterArgument *arg = reinterpret_cast<TidReporterArgument *>(argument); 969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_lock(&arg->tid_reported_mutex); 979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson arg->reported_tid = GetTid(); 989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_broadcast(&arg->tid_reported_cond); 999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_unlock(&arg->tid_reported_mutex); 1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_lock(&arg->terminate_thread_mutex); 1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (!arg->terminate_thread) 1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_wait(&arg->terminate_thread_cond, 1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson &arg->terminate_thread_mutex); 1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_unlock(&arg->terminate_thread_mutex); 1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return NULL; 1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid ThreadListerTest::SpawnTidReporter(pthread_t *pthread_id, 1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pid_t *tid) { 1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_lock(&thread_arg.tid_reported_mutex); 1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson thread_arg.reported_tid = -1; 1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_create(pthread_id, NULL, 1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson TidReporterThread, 1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson &thread_arg)); 1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (thread_arg.reported_tid == -1) 1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_cond_wait(&thread_arg.tid_reported_cond, 1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson &thread_arg.tid_reported_mutex); 1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_mutex_unlock(&thread_arg.tid_reported_mutex); 1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *tid = thread_arg.reported_tid; 1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonstatic std::vector<pid_t> ReadTidsToVector(ThreadLister *thread_lister) { 1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::vector<pid_t> listed_tids; 1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pid_t tid; 1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while ((tid = thread_lister->GetNextTID()) >= 0) 1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson listed_tids.push_back(tid); 1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_FALSE(thread_lister->error()); 1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return listed_tids; 1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonstatic bool Includes(std::vector<pid_t> first, std::vector<pid_t> second) { 1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::sort(first.begin(), first.end()); 1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::sort(second.begin(), second.end()); 1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return std::includes(first.begin(), first.end(), 1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson second.begin(), second.end()); 1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonstatic bool HasElement(std::vector<pid_t> vector, pid_t element) { 1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return std::find(vector.begin(), vector.end(), element) != vector.end(); 1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// ThreadLister's output should include the current thread's TID and the TID of 1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// every thread we spawned. 1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST_F(ThreadListerTest, ThreadListerSeesAllSpawnedThreads) { 1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pid_t self_tid = GetTid(); 1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ThreadLister thread_lister(getpid()); 1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister); 1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_TRUE(HasElement(listed_tids, self_tid)); 1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_TRUE(Includes(listed_tids, tids_)); 1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Calling Reset() should not cause ThreadLister to forget any threads it's 1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// supposed to know about. 1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST_F(ThreadListerTest, ResetDoesNotForgetThreads) { 1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ThreadLister thread_lister(getpid()); 1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Run the loop body twice, because Reset() might behave differently if called 1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // on a freshly created object. 1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (uptr i = 0; i < 2; i++) { 1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson thread_lister.Reset(); 1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister); 1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_TRUE(Includes(listed_tids, tids_)); 1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// If new threads have spawned during ThreadLister object's lifetime, calling 1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Reset() should cause ThreadLister to recognize their existence. 1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST_F(ThreadListerTest, ResetMakesNewThreadsKnown) { 1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ThreadLister thread_lister(getpid()); 1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::vector<pid_t> threads_before_extra = ReadTidsToVector(&thread_lister); 1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_t extra_pthread_id; 1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pid_t extra_tid; 1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson SpawnTidReporter(&extra_pthread_id, &extra_tid); 1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Register the new thread so it gets terminated in TearDown(). 1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_ids_.push_back(extra_pthread_id); 1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // It would be very bizarre if the new TID had been listed before we even 1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // spawned that thread, but it would also cause a false success in this test, 1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // so better check for that. 1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_FALSE(HasElement(threads_before_extra, extra_tid)); 1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson thread_lister.Reset(); 1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson std::vector<pid_t> threads_after_extra = ReadTidsToVector(&thread_lister); 1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_TRUE(HasElement(threads_after_extra, extra_tid)); 1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST(SanitizerCommon, SetEnvTest) { 1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson const char kEnvName[] = "ENV_FOO"; 1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson SetEnv(kEnvName, "value"); 1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_STREQ("value", getenv(kEnvName)); 1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson unsetenv(kEnvName); 1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_EQ(0, getenv(kEnvName)); 1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#if defined(__x86_64__) || defined(__i386__) 1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid *thread_self_offset_test_func(void *arg) { 2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson bool result = 2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *(uptr *)((char *)ThreadSelf() + ThreadSelfOffset()) == ThreadSelf(); 2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return (void *)result; 2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST(SanitizerLinux, ThreadSelfOffset) { 2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_TRUE((bool)thread_self_offset_test_func(0)); 2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_t tid; 2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson void *result; 2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_create(&tid, 0, thread_self_offset_test_func, 0)); 2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_join(tid, &result)); 2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_TRUE((bool)result); 2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// libpthread puts the thread descriptor at the end of stack space. 2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid *thread_descriptor_size_test_func(void *arg) { 2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson uptr descr_addr = ThreadSelf(); 2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_attr_t attr; 2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_getattr_np(pthread_self(), &attr); 2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson void *stackaddr; 2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson size_t stacksize; 2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_attr_getstack(&attr, &stackaddr, &stacksize); 2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return (void *)((uptr)stackaddr + stacksize - descr_addr); 2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST(SanitizerLinux, ThreadDescriptorSize) { 2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_t tid; 2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson void *result; 2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_create(&tid, 0, thread_descriptor_size_test_func, 0)); 2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_join(tid, &result)); 2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_EQ((uptr)result, ThreadDescriptorSize()); 2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#endif 2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST(SanitizerCommon, LibraryNameIs) { 2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_FALSE(LibraryNameIs("", "")); 2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson char full_name[256]; 2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson const char *paths[] = { "", "/", "/path/to/" }; 2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson const char *suffixes[] = { "", "-linux", ".1.2", "-linux.1.2" }; 2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson const char *base_names[] = { "lib", "lib.0", "lib-i386" }; 2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson const char *wrong_names[] = { "", "lib.9", "lib-x86_64" }; 2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (uptr i = 0; i < ARRAY_SIZE(paths); i++) 2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (uptr j = 0; j < ARRAY_SIZE(suffixes); j++) { 2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (uptr k = 0; k < ARRAY_SIZE(base_names); k++) { 2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson internal_snprintf(full_name, ARRAY_SIZE(full_name), "%s%s%s.so", 2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson paths[i], base_names[k], suffixes[j]); 2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_TRUE(LibraryNameIs(full_name, base_names[k])) 2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson << "Full name " << full_name 2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson << " doesn't match base name " << base_names[k]; 2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (uptr m = 0; m < ARRAY_SIZE(wrong_names); m++) 2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_FALSE(LibraryNameIs(full_name, wrong_names[m])) 2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson << "Full name " << full_name 2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson << " matches base name " << wrong_names[m]; 2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpthread_key_t key; 2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonbool destructor_executed; 2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonextern "C" 2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid destructor(void *arg) { 2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson uptr iter = reinterpret_cast<uptr>(arg); 2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (iter > 1) { 2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast<void *>(iter - 1))); 2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return; 2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson destructor_executed = true; 2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonextern "C" 2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid *thread_func(void *arg) { 2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return reinterpret_cast<void*>(pthread_setspecific(key, arg)); 2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid SpawnThread(uptr iteration) { 2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson destructor_executed = false; 2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson pthread_t tid; 2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_create(&tid, 0, &thread_func, 2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson reinterpret_cast<void *>(iteration))); 2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson void *retval; 2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_join(tid, &retval)); 2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, retval); 2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonTEST(SanitizerCommon, PthreadDestructorIterations) { 2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ASSERT_EQ(0, pthread_key_create(&key, &destructor)); 2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson SpawnThread(kPthreadDestructorIterations); 2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_TRUE(destructor_executed); 2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson SpawnThread(kPthreadDestructorIterations + 1); 2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson EXPECT_FALSE(destructor_executed); 2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} // namespace __sanitizer 2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#endif // SANITIZER_LINUX 2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson