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 |