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