1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sandbox/linux/services/thread_helpers.h" 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <sys/stat.h> 10 #include <sys/types.h> 11 #include <unistd.h> 12 13 #include "base/logging.h" 14 #include "base/macros.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/posix/eintr_wrapper.h" 17 #include "base/process/process_metrics.h" 18 #include "base/threading/platform_thread.h" 19 #include "base/threading/thread.h" 20 #include "build/build_config.h" 21 #include "sandbox/linux/tests/unit_tests.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 using base::PlatformThread; 25 26 namespace sandbox { 27 28 namespace { 29 30 // These tests fail under ThreadSanitizer, see http://crbug.com/342305 31 #if !defined(THREAD_SANITIZER) 32 33 int GetRaceTestIterations() { 34 if (IsRunningOnValgrind()) { 35 return 2; 36 } else { 37 return 1000; 38 } 39 } 40 41 class ScopedProc { 42 public: 43 ScopedProc() : fd_(-1) { 44 fd_ = open("/proc/", O_RDONLY | O_DIRECTORY); 45 CHECK_LE(0, fd_); 46 } 47 48 ~ScopedProc() { PCHECK(0 == IGNORE_EINTR(close(fd_))); } 49 50 int fd() { return fd_; } 51 52 private: 53 int fd_; 54 DISALLOW_COPY_AND_ASSIGN(ScopedProc); 55 }; 56 57 TEST(ThreadHelpers, IsSingleThreadedBasic) { 58 ScopedProc proc_fd; 59 ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 60 ASSERT_TRUE(ThreadHelpers::IsSingleThreaded()); 61 62 base::Thread thread("sandbox_tests"); 63 ASSERT_TRUE(ThreadHelpers::StartThreadAndWatchProcFS(proc_fd.fd(), &thread)); 64 ASSERT_FALSE(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 65 ASSERT_FALSE(ThreadHelpers::IsSingleThreaded()); 66 // Explicitly stop the thread here to not pollute the next test. 67 ASSERT_TRUE(ThreadHelpers::StopThreadAndWatchProcFS(proc_fd.fd(), &thread)); 68 } 69 70 SANDBOX_TEST(ThreadHelpers, AssertSingleThreaded) { 71 ScopedProc proc_fd; 72 SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 73 SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded()); 74 75 ThreadHelpers::AssertSingleThreaded(proc_fd.fd()); 76 ThreadHelpers::AssertSingleThreaded(); 77 } 78 79 TEST(ThreadHelpers, IsSingleThreadedIterated) { 80 ScopedProc proc_fd; 81 ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 82 83 // Iterate to check for race conditions. 84 for (int i = 0; i < GetRaceTestIterations(); ++i) { 85 base::Thread thread("sandbox_tests"); 86 ASSERT_TRUE( 87 ThreadHelpers::StartThreadAndWatchProcFS(proc_fd.fd(), &thread)); 88 ASSERT_FALSE(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 89 // Explicitly stop the thread here to not pollute the next test. 90 ASSERT_TRUE(ThreadHelpers::StopThreadAndWatchProcFS(proc_fd.fd(), &thread)); 91 } 92 } 93 94 TEST(ThreadHelpers, IsSingleThreadedStartAndStop) { 95 ScopedProc proc_fd; 96 ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 97 98 base::Thread thread("sandbox_tests"); 99 // This is testing for a race condition, so iterate. 100 // Manually, this has been tested with more that 1M iterations. 101 for (int i = 0; i < GetRaceTestIterations(); ++i) { 102 ASSERT_TRUE( 103 ThreadHelpers::StartThreadAndWatchProcFS(proc_fd.fd(), &thread)); 104 ASSERT_FALSE(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 105 106 ASSERT_TRUE(ThreadHelpers::StopThreadAndWatchProcFS(proc_fd.fd(), &thread)); 107 ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(proc_fd.fd())); 108 ASSERT_EQ(1, base::GetNumberOfThreads(base::GetCurrentProcessHandle())); 109 } 110 } 111 112 SANDBOX_TEST(ThreadHelpers, AssertSingleThreadedAfterThreadStopped) { 113 ScopedProc proc_fd; 114 SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded()); 115 116 base::Thread thread1("sandbox_tests"); 117 base::Thread thread2("sandbox_tests"); 118 119 for (int i = 0; i < GetRaceTestIterations(); ++i) { 120 SANDBOX_ASSERT( 121 ThreadHelpers::StartThreadAndWatchProcFS(proc_fd.fd(), &thread1)); 122 SANDBOX_ASSERT( 123 ThreadHelpers::StartThreadAndWatchProcFS(proc_fd.fd(), &thread2)); 124 SANDBOX_ASSERT(!ThreadHelpers::IsSingleThreaded()); 125 126 thread1.Stop(); 127 thread2.Stop(); 128 // This will wait on /proc/ to reflect the state of threads in the 129 // process. 130 ThreadHelpers::AssertSingleThreaded(); 131 SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded()); 132 } 133 } 134 135 // Only run this test in Debug mode, where AssertSingleThreaded() will return 136 // in less than 64ms. 137 #if !defined(NDEBUG) 138 SANDBOX_DEATH_TEST( 139 ThreadHelpers, 140 AssertSingleThreadedDies, 141 DEATH_MESSAGE( 142 ThreadHelpers::GetAssertSingleThreadedErrorMessageForTests())) { 143 base::Thread thread1("sandbox_tests"); 144 SANDBOX_ASSERT(thread1.Start()); 145 ThreadHelpers::AssertSingleThreaded(); 146 } 147 #endif // !defined(NDEBUG) 148 149 #endif // !defined(THREAD_SANITIZER) 150 151 } // namespace 152 153 } // namespace sandbox 154