Chromium Code Reviews| 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 // Note, this must use all native functions to avoid instantiating the | |
| 23 // ActiveVerifier. e.g. can't use base::Thread or even base::PlatformThread. | |
| 24 DWORD __stdcall ThreadFunc(void* params) { | |
| 25 HANDLE handle = ::CreateMutex(nullptr, false, nullptr); | |
| 26 HANDLE event = reinterpret_cast<HANDLE>(params); | |
| 27 ::WaitForSingleObject(event, INFINITE); | |
| 28 ScopedHandle handle_holder(handle); | |
|
scottmg
2016/03/11 22:13:09
Does ActiveVerifier CHECK or DCHECK? Do we need to
Will Harris
2016/03/11 22:23:44
it does a CHECK, so it is certainly quite fatal.
scottmg
2016/03/11 22:29:00
OK, I was more worried about this test becoming po
Will Harris
2016/03/11 23:07:47
Acknowledged.
| |
| 29 return 0; | |
| 30 } | |
| 31 | |
| 32 bool InternalRunThreadTest() { | |
| 33 std::vector<HANDLE> threads_; | |
| 34 // From manual testing, the bug fixed by crrev.com/678736a starts reliably | |
| 35 // causing handle verifier asserts to trigger at around 100 threads, so make | |
| 36 // it 200 to be sure to detect any future regressions. | |
| 37 const size_t kNumThreads = 200; | |
| 38 | |
| 39 // bManualReset is set to true to allow signalling multiple threads. | |
| 40 HANDLE start_event = ::CreateEvent(nullptr, true, false, nullptr); | |
| 41 if (!start_event) | |
| 42 return false; | |
| 43 | |
| 44 for (size_t i = 0; i < kNumThreads; i++) { | |
| 45 HANDLE thread_handle = | |
| 46 ::CreateThread(nullptr, 0, ThreadFunc, | |
| 47 reinterpret_cast<void*>(start_event), 0, nullptr); | |
| 48 if (!thread_handle) | |
| 49 break; | |
| 50 threads_.push_back(thread_handle); | |
| 51 } | |
| 52 | |
| 53 if (threads_.size() != kNumThreads) { | |
|
scottmg
2016/03/11 22:13:09
I wouldn't bother with this, just return false ins
Will Harris
2016/03/11 22:23:44
bah why u not like my cleanup code?
scottmg
2016/03/11 22:29:00
I don't really care either way. You can keep it if
Will Harris
2016/03/11 23:07:47
I left it. I hate leaks.
scottmg
2016/03/11 23:14:19
You wouldn't appreciate the irony of a handle-chec
| |
| 54 for (const auto& thread : threads_) | |
| 55 ::CloseHandle(thread); | |
| 56 ::CloseHandle(start_event); | |
| 57 return false; | |
| 58 } | |
| 59 | |
| 60 ::SetEvent(start_event); | |
| 61 ::CloseHandle(start_event); | |
| 62 for (const auto& thread : threads_) { | |
| 63 ::WaitForSingleObject(thread, INFINITE); | |
| 64 ::CloseHandle(thread); | |
| 65 } | |
| 66 | |
| 67 return true; | |
| 68 } | |
| 69 | |
| 70 bool InternalRunLocationTest() { | |
| 71 // Create a new handle and then set LastError again. | |
| 72 HANDLE handle = ::CreateMutex(nullptr, false, nullptr); | |
| 73 if (!handle) | |
| 74 return false; | |
| 75 ScopedHandle handle_holder(handle); | |
| 76 | |
| 77 HMODULE verifier_module = GetHandleVerifierModuleForTesting(); | |
| 78 if (!verifier_module) | |
| 79 return false; | |
| 80 | |
| 81 // Get my module | |
| 82 HMODULE my_module = reinterpret_cast<HMODULE>(&__ImageBase); | |
| 83 if (!my_module) | |
| 84 return false; | |
| 85 | |
| 86 HMODULE main_module = ::GetModuleHandle(NULL); | |
| 87 | |
| 88 #if defined(COMPONENT_BUILD) | |
| 89 // In a component build ActiveVerifier will always be created inside base.dll | |
| 90 // as the code always lives there. | |
| 91 if (verifier_module == my_module || verifier_module == main_module) | |
| 92 return false; | |
| 93 #else | |
| 94 // In a non-component build, ActiveVerifier should always be created in the | |
| 95 // version of base linked with the main executable. | |
| 96 if (verifier_module == my_module || verifier_module != main_module) | |
| 97 return false; | |
| 98 #endif | |
| 99 return true; | |
| 100 } | |
| 101 | |
| 102 } // namespace | |
| 103 | |
| 104 bool RunTest() { | |
| 105 return InternalRunThreadTest() && InternalRunLocationTest(); | |
| 106 } | |
| 107 | |
| 108 } // testing | |
| 109 } // win | |
| 110 } // base | |
| OLD | NEW |