OLD | NEW |
1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "snapshot/win/process_reader_win.h" | 15 #include "snapshot/win/process_reader_win.h" |
16 | 16 |
17 #include <string.h> | 17 #include <string.h> |
18 #include <windows.h> | 18 #include <windows.h> |
19 | 19 |
20 #include "gtest/gtest.h" | 20 #include "gtest/gtest.h" |
21 #include "test/win/win_multiprocess.h" | 21 #include "test/win/win_multiprocess.h" |
| 22 #include "util/synchronization/semaphore.h" |
| 23 #include "util/thread/thread.h" |
22 #include "util/win/scoped_process_suspend.h" | 24 #include "util/win/scoped_process_suspend.h" |
23 | 25 |
24 namespace crashpad { | 26 namespace crashpad { |
25 namespace test { | 27 namespace test { |
26 namespace { | 28 namespace { |
27 | 29 |
28 TEST(ProcessReaderWin, SelfBasic) { | 30 TEST(ProcessReaderWin, SelfBasic) { |
29 ProcessReaderWin process_reader; | 31 ProcessReaderWin process_reader; |
30 ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(), | 32 ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(), |
31 ProcessSuspensionState::kRunning)); | 33 ProcessSuspensionState::kRunning)); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 ProcessSuspensionState::kRunning)); | 99 ProcessSuspensionState::kRunning)); |
98 | 100 |
99 const std::vector<ProcessReaderWin::Thread>& threads = | 101 const std::vector<ProcessReaderWin::Thread>& threads = |
100 process_reader.Threads(); | 102 process_reader.Threads(); |
101 | 103 |
102 // If other tests ran in this process previously, threads may have been | 104 // If other tests ran in this process previously, threads may have been |
103 // created and may still be running. This check must look for at least one | 105 // created and may still be running. This check must look for at least one |
104 // thread, not exactly one thread. | 106 // thread, not exactly one thread. |
105 ASSERT_GE(threads.size(), 1u); | 107 ASSERT_GE(threads.size(), 1u); |
106 | 108 |
107 EXPECT_EQ(GetThreadId(GetCurrentThread()), threads[0].id); | 109 EXPECT_EQ(GetCurrentThreadId(), threads[0].id); |
108 #if defined(ARCH_CPU_64_BITS) | 110 #if defined(ARCH_CPU_64_BITS) |
109 EXPECT_NE(0, threads[0].context.Rip); | 111 EXPECT_NE(0, threads[0].context.Rip); |
110 #else | 112 #else |
111 EXPECT_NE(0u, threads[0].context.Eip); | 113 EXPECT_NE(0u, threads[0].context.Eip); |
112 #endif | 114 #endif |
113 | 115 |
114 EXPECT_EQ(0, threads[0].suspend_count); | 116 EXPECT_EQ(0, threads[0].suspend_count); |
115 } | 117 } |
116 | 118 |
117 class ProcessReaderChildThreadSuspendCount final : public WinMultiprocess { | 119 class ProcessReaderChildThreadSuspendCount final : public WinMultiprocess { |
118 public: | 120 public: |
119 ProcessReaderChildThreadSuspendCount() : WinMultiprocess() {} | 121 ProcessReaderChildThreadSuspendCount() : WinMultiprocess() {} |
120 ~ProcessReaderChildThreadSuspendCount() {} | 122 ~ProcessReaderChildThreadSuspendCount() {} |
121 | 123 |
122 private: | 124 private: |
| 125 enum : unsigned int { kCreatedThreads = 3 }; |
| 126 |
| 127 class SleepingThread : public Thread { |
| 128 public: |
| 129 SleepingThread() : done_(nullptr) {} |
| 130 |
| 131 void SetHandle(Semaphore* done) { |
| 132 done_= done; |
| 133 } |
| 134 |
| 135 void ThreadMain() override { |
| 136 done_->Wait(); |
| 137 }; |
| 138 |
| 139 private: |
| 140 Semaphore* done_; |
| 141 }; |
| 142 |
123 void WinMultiprocessParent() override { | 143 void WinMultiprocessParent() override { |
| 144 char c; |
| 145 CheckedReadFile(ReadPipeHandle(), &c, sizeof(c)); |
| 146 ASSERT_EQ(' ', c); |
| 147 |
124 { | 148 { |
125 ProcessReaderWin process_reader; | 149 ProcessReaderWin process_reader; |
126 ASSERT_TRUE(process_reader.Initialize(ChildProcess(), | 150 ASSERT_TRUE(process_reader.Initialize(ChildProcess(), |
127 ProcessSuspensionState::kRunning)); | 151 ProcessSuspensionState::kRunning)); |
128 | 152 |
129 const auto& threads = process_reader.Threads(); | 153 const auto& threads = process_reader.Threads(); |
130 ASSERT_FALSE(threads.empty()); | 154 ASSERT_GE(threads.size(), kCreatedThreads + 1); |
131 for (const auto& thread : threads) | 155 for (const auto& thread : threads) |
132 EXPECT_EQ(0u, thread.suspend_count); | 156 EXPECT_EQ(0u, thread.suspend_count); |
133 } | 157 } |
134 | 158 |
135 { | 159 { |
136 ScopedProcessSuspend suspend(ChildProcess()); | 160 ScopedProcessSuspend suspend(ChildProcess()); |
137 | 161 |
138 ProcessReaderWin process_reader; | 162 ProcessReaderWin process_reader; |
139 ASSERT_TRUE(process_reader.Initialize( | 163 ASSERT_TRUE(process_reader.Initialize( |
140 ChildProcess(), ProcessSuspensionState::kSuspended)); | 164 ChildProcess(), ProcessSuspensionState::kSuspended)); |
141 | 165 |
142 // Confirm that thread counts are adjusted correctly for the process being | 166 // Confirm that thread counts are adjusted correctly for the process being |
143 // suspended. | 167 // suspended. |
144 const auto& threads = process_reader.Threads(); | 168 const auto& threads = process_reader.Threads(); |
145 ASSERT_FALSE(threads.empty()); | 169 ASSERT_GE(threads.size(), kCreatedThreads + 1); |
146 for (const auto& thread : threads) | 170 for (const auto& thread : threads) |
147 EXPECT_EQ(0u, thread.suspend_count); | 171 EXPECT_EQ(0u, thread.suspend_count); |
148 } | 172 } |
149 } | 173 } |
150 | 174 |
151 void WinMultiprocessChild() override { | 175 void WinMultiprocessChild() override { |
152 WinVMAddress address = reinterpret_cast<WinVMAddress>(kTestMemory); | 176 // Create three dummy threads so we can confirm we read successfully read |
153 CheckedWriteFile(WritePipeHandle(), &address, sizeof(address)); | 177 // more than just the main thread. |
| 178 SleepingThread threads[kCreatedThreads]; |
| 179 Semaphore done(0); |
| 180 for (auto& thread : threads) |
| 181 thread.SetHandle(&done); |
| 182 for (auto& thread : threads) |
| 183 thread.Start(); |
| 184 |
| 185 char c = ' '; |
| 186 CheckedWriteFile(WritePipeHandle(), &c, sizeof(c)); |
154 | 187 |
155 // Wait for the parent to signal that it's OK to exit by closing its end of | 188 // Wait for the parent to signal that it's OK to exit by closing its end of |
156 // the pipe. | 189 // the pipe. |
157 CheckedReadFileAtEOF(ReadPipeHandle()); | 190 CheckedReadFileAtEOF(ReadPipeHandle()); |
| 191 |
| 192 for (int i = 0; i < arraysize(threads); ++i) |
| 193 done.Signal(); |
| 194 for (auto& thread : threads) |
| 195 thread.Join(); |
158 } | 196 } |
159 | 197 |
160 DISALLOW_COPY_AND_ASSIGN(ProcessReaderChildThreadSuspendCount); | 198 DISALLOW_COPY_AND_ASSIGN(ProcessReaderChildThreadSuspendCount); |
161 }; | 199 }; |
162 | 200 |
163 TEST(ProcessReaderWin, ChildThreadSuspendCounts) { | 201 TEST(ProcessReaderWin, ChildThreadSuspendCounts) { |
164 WinMultiprocess::Run<ProcessReaderChildThreadSuspendCount>(); | 202 WinMultiprocess::Run<ProcessReaderChildThreadSuspendCount>(); |
165 } | 203 } |
166 | 204 |
167 } // namespace | 205 } // namespace |
168 } // namespace test | 206 } // namespace test |
169 } // namespace crashpad | 207 } // namespace crashpad |
OLD | NEW |