OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 <windows.h> |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/win/scoped_handle.h" |
| 10 |
| 11 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx |
| 12 extern "C" IMAGE_DOS_HEADER __ImageBase; |
| 13 |
| 14 namespace base { |
| 15 namespace win { |
| 16 namespace testing { |
| 17 |
| 18 extern "C" bool __declspec(dllexport) RunTest(); |
| 19 |
| 20 namespace { |
| 21 |
| 22 struct ThreadParams { |
| 23 HANDLE ready_event; |
| 24 HANDLE start_event; |
| 25 }; |
| 26 |
| 27 // Note, this must use all native functions to avoid instantiating the |
| 28 // ActiveVerifier. e.g. can't use base::Thread or even base::PlatformThread. |
| 29 DWORD __stdcall ThreadFunc(void* params) { |
| 30 ThreadParams* thread_params = reinterpret_cast<ThreadParams*>(params); |
| 31 HANDLE handle = ::CreateMutex(nullptr, false, nullptr); |
| 32 |
| 33 ::SetEvent(thread_params->ready_event); |
| 34 ::WaitForSingleObject(thread_params->start_event, INFINITE); |
| 35 ScopedHandle handle_holder(handle); |
| 36 return 0; |
| 37 } |
| 38 |
| 39 bool InternalRunThreadTest() { |
| 40 std::vector<HANDLE> threads_; |
| 41 // From manual testing, the bug fixed by crrev.com/678736a starts reliably |
| 42 // causing handle verifier asserts to trigger at around 100 threads, so make |
| 43 // it 200 to be sure to detect any future regressions. |
| 44 const size_t kNumThreads = 200; |
| 45 |
| 46 // bManualReset is set to true to allow signalling multiple threads. |
| 47 HANDLE start_event = ::CreateEvent(nullptr, true, false, nullptr); |
| 48 if (!start_event) |
| 49 return false; |
| 50 |
| 51 HANDLE ready_event = CreateEvent(nullptr, false, false, nullptr); |
| 52 if (!ready_event) |
| 53 return false; |
| 54 |
| 55 ThreadParams thread_params = { ready_event, start_event }; |
| 56 |
| 57 for (size_t i = 0; i < kNumThreads; i++) { |
| 58 HANDLE thread_handle = |
| 59 ::CreateThread(nullptr, 0, ThreadFunc, |
| 60 reinterpret_cast<void*>(&thread_params), 0, nullptr); |
| 61 if (!thread_handle) |
| 62 break; |
| 63 ::WaitForSingleObject(ready_event, INFINITE); |
| 64 threads_.push_back(thread_handle); |
| 65 } |
| 66 |
| 67 ::CloseHandle(ready_event); |
| 68 |
| 69 if (threads_.size() != kNumThreads) { |
| 70 for (const auto& thread : threads_) |
| 71 ::CloseHandle(thread); |
| 72 ::CloseHandle(start_event); |
| 73 return false; |
| 74 } |
| 75 |
| 76 ::SetEvent(start_event); |
| 77 ::CloseHandle(start_event); |
| 78 for (const auto& thread : threads_) { |
| 79 ::WaitForSingleObject(thread, INFINITE); |
| 80 ::CloseHandle(thread); |
| 81 } |
| 82 |
| 83 return true; |
| 84 } |
| 85 |
| 86 bool InternalRunLocationTest() { |
| 87 // Create a new handle and then set LastError again. |
| 88 HANDLE handle = ::CreateMutex(nullptr, false, nullptr); |
| 89 if (!handle) |
| 90 return false; |
| 91 ScopedHandle handle_holder(handle); |
| 92 |
| 93 HMODULE verifier_module = GetHandleVerifierModuleForTesting(); |
| 94 if (!verifier_module) |
| 95 return false; |
| 96 |
| 97 // Get my module |
| 98 HMODULE my_module = reinterpret_cast<HMODULE>(&__ImageBase); |
| 99 if (!my_module) |
| 100 return false; |
| 101 |
| 102 HMODULE main_module = ::GetModuleHandle(NULL); |
| 103 |
| 104 #if defined(COMPONENT_BUILD) |
| 105 // In a component build ActiveVerifier will always be created inside base.dll |
| 106 // as the code always lives there. |
| 107 if (verifier_module == my_module || verifier_module == main_module) |
| 108 return false; |
| 109 #else |
| 110 // In a non-component build, ActiveVerifier should always be created in the |
| 111 // version of base linked with the main executable. |
| 112 if (verifier_module == my_module || verifier_module != main_module) |
| 113 return false; |
| 114 #endif |
| 115 return true; |
| 116 } |
| 117 |
| 118 } // namespace |
| 119 |
| 120 bool RunTest() { |
| 121 return InternalRunThreadTest() && InternalRunLocationTest(); |
| 122 } |
| 123 |
| 124 } // testing |
| 125 } // win |
| 126 } // base |
OLD | NEW |