sanitizer_linux_test.cc revision 827d4ef8b76760ef8c58612d916b8f53081bf368
1//===-- sanitizer_linux_test.cc -------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Tests for sanitizer_linux.h 11// 12//===----------------------------------------------------------------------===// 13 14#ifdef __linux__ 15 16#include "sanitizer_common/sanitizer_linux.h" 17#include "gtest/gtest.h" 18 19#include "sanitizer_common/sanitizer_common.h" 20 21#include <pthread.h> 22#include <sched.h> 23 24#include <algorithm> 25#include <vector> 26 27namespace __sanitizer { 28 29struct TidReporterArgument { 30 TidReporterArgument() { 31 pthread_mutex_init(&terminate_thread_mutex, NULL); 32 pthread_mutex_init(&tid_reported_mutex, NULL); 33 pthread_cond_init(&terminate_thread_cond, NULL); 34 pthread_cond_init(&tid_reported_cond, NULL); 35 terminate_thread = false; 36 } 37 38 ~TidReporterArgument() { 39 pthread_mutex_destroy(&terminate_thread_mutex); 40 pthread_mutex_destroy(&tid_reported_mutex); 41 pthread_cond_destroy(&terminate_thread_cond); 42 pthread_cond_destroy(&tid_reported_cond); 43 } 44 45 pid_t reported_tid; 46 // For signaling to spawned threads that they should terminate. 47 pthread_cond_t terminate_thread_cond; 48 pthread_mutex_t terminate_thread_mutex; 49 bool terminate_thread; 50 // For signaling to main thread that a child thread has reported its tid. 51 pthread_cond_t tid_reported_cond; 52 pthread_mutex_t tid_reported_mutex; 53 54 private: 55 // Disallow evil constructors 56 TidReporterArgument(const TidReporterArgument &); 57 void operator=(const TidReporterArgument &); 58}; 59 60class ThreadListerTest : public ::testing::Test { 61 protected: 62 virtual void SetUp() { 63 pthread_t pthread_id; 64 pid_t tid; 65 for (uptr i = 0; i < kThreadCount; i++) { 66 SpawnTidReporter(&pthread_id, &tid); 67 pthread_ids_.push_back(pthread_id); 68 tids_.push_back(tid); 69 } 70 } 71 72 virtual void TearDown() { 73 pthread_mutex_lock(&thread_arg.terminate_thread_mutex); 74 thread_arg.terminate_thread = true; 75 pthread_cond_broadcast(&thread_arg.terminate_thread_cond); 76 pthread_mutex_unlock(&thread_arg.terminate_thread_mutex); 77 for (uptr i = 0; i < pthread_ids_.size(); i++) 78 pthread_join(pthread_ids_[i], NULL); 79 } 80 81 void SpawnTidReporter(pthread_t *pthread_id, pid_t *tid); 82 83 static const uptr kThreadCount = 20; 84 85 std::vector<pthread_t> pthread_ids_; 86 std::vector<pid_t> tids_; 87 88 TidReporterArgument thread_arg; 89}; 90 91// Writes its TID once to reported_tid and waits until signaled to terminate. 92void *TidReporterThread(void *argument) { 93 TidReporterArgument *arg = reinterpret_cast<TidReporterArgument *>(argument); 94 pthread_mutex_lock(&arg->tid_reported_mutex); 95 arg->reported_tid = GetTid(); 96 pthread_cond_broadcast(&arg->tid_reported_cond); 97 pthread_mutex_unlock(&arg->tid_reported_mutex); 98 99 pthread_mutex_lock(&arg->terminate_thread_mutex); 100 while (!arg->terminate_thread) 101 pthread_cond_wait(&arg->terminate_thread_cond, 102 &arg->terminate_thread_mutex); 103 pthread_mutex_unlock(&arg->terminate_thread_mutex); 104 return NULL; 105} 106 107void ThreadListerTest::SpawnTidReporter(pthread_t *pthread_id, 108 pid_t *tid) { 109 pthread_mutex_lock(&thread_arg.tid_reported_mutex); 110 thread_arg.reported_tid = -1; 111 ASSERT_EQ(0, pthread_create(pthread_id, NULL, 112 TidReporterThread, 113 &thread_arg)); 114 while (thread_arg.reported_tid == -1) 115 pthread_cond_wait(&thread_arg.tid_reported_cond, 116 &thread_arg.tid_reported_mutex); 117 pthread_mutex_unlock(&thread_arg.tid_reported_mutex); 118 *tid = thread_arg.reported_tid; 119} 120 121static std::vector<pid_t> ReadTidsToVector(ThreadLister *thread_lister) { 122 std::vector<pid_t> listed_tids; 123 pid_t tid; 124 while ((tid = thread_lister->GetNextTID()) >= 0) 125 listed_tids.push_back(tid); 126 EXPECT_FALSE(thread_lister->error()); 127 return listed_tids; 128} 129 130static bool Includes(std::vector<pid_t> first, std::vector<pid_t> second) { 131 std::sort(first.begin(), first.end()); 132 std::sort(second.begin(), second.end()); 133 return std::includes(first.begin(), first.end(), 134 second.begin(), second.end()); 135} 136 137static bool HasElement(std::vector<pid_t> vector, pid_t element) { 138 return std::find(vector.begin(), vector.end(), element) != vector.end(); 139} 140 141// ThreadLister's output should include the current thread's TID and the TID of 142// every thread we spawned. 143TEST_F(ThreadListerTest, ThreadListerSeesAllSpawnedThreads) { 144 pid_t self_tid = GetTid(); 145 ThreadLister thread_lister(getpid()); 146 std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister); 147 ASSERT_TRUE(HasElement(listed_tids, self_tid)); 148 ASSERT_TRUE(Includes(listed_tids, tids_)); 149} 150 151// Calling Reset() should not cause ThreadLister to forget any threads it's 152// supposed to know about. 153TEST_F(ThreadListerTest, ResetDoesNotForgetThreads) { 154 ThreadLister thread_lister(getpid()); 155 156 // Run the loop body twice, because Reset() might behave differently if called 157 // on a freshly created object. 158 for (uptr i = 0; i < 2; i++) { 159 thread_lister.Reset(); 160 std::vector<pid_t> listed_tids = ReadTidsToVector(&thread_lister); 161 ASSERT_TRUE(Includes(listed_tids, tids_)); 162 } 163} 164 165// If new threads have spawned during ThreadLister object's lifetime, calling 166// Reset() should cause ThreadLister to recognize their existence. 167TEST_F(ThreadListerTest, ResetMakesNewThreadsKnown) { 168 ThreadLister thread_lister(getpid()); 169 std::vector<pid_t> threads_before_extra = ReadTidsToVector(&thread_lister); 170 171 pthread_t extra_pthread_id; 172 pid_t extra_tid; 173 SpawnTidReporter(&extra_pthread_id, &extra_tid); 174 // Register the new thread so it gets terminated in TearDown(). 175 pthread_ids_.push_back(extra_pthread_id); 176 177 // It would be very bizarre if the new TID had been listed before we even 178 // spawned that thread, but it would also cause a false success in this test, 179 // so better check for that. 180 ASSERT_FALSE(HasElement(threads_before_extra, extra_tid)); 181 182 thread_lister.Reset(); 183 184 std::vector<pid_t> threads_after_extra = ReadTidsToVector(&thread_lister); 185 ASSERT_TRUE(HasElement(threads_after_extra, extra_tid)); 186} 187 188} // namespace __sanitizer 189 190#endif // __linux__ 191