File: scoped_handle_test_dll.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (136 lines) | stat: -rw-r--r-- 3,618 bytes parent folder | download | duplicates (6)
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