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