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