| 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 |