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