scoped_handle_test_dll.cc 3.5 KB

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