Home | History | Annotate | Download | only in services
      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