1 // Copyright (c) 2012 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.
5 #include "base/win/scoped_handle.h"
7 #include <unordered_map>
9 #include "base/debug/alias.h"
10 #include "base/hash.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/synchronization/lock_impl.h"
18 size_t operator()(const HANDLE
& handle
) const {
19 char buffer
[sizeof(handle
)];
20 memcpy(buffer
, &handle
, sizeof(handle
));
21 return base::Hash(buffer
, sizeof(buffer
));
31 typedef std::unordered_map
<HANDLE
, Info
, HandleHash
> HandleMap
;
33 // g_lock protects g_handle_map and g_closing.
34 typedef base::internal::LockImpl NativeLock
;
35 base::LazyInstance
<NativeLock
>::Leaky g_lock
= LAZY_INSTANCE_INITIALIZER
;
36 base::LazyInstance
<HandleMap
>::Leaky g_handle_map
= LAZY_INSTANCE_INITIALIZER
;
37 bool g_closing
= false;
39 // g_verifier_enabled is not protected by g_lock because that would require
40 // using the lock (hence, synchornizing multiple threads) even when the
41 // verifier is not in use. Note that this variable is initialized to track all
42 // handles, and it should only move to the disabled state, and never back to
43 // enabled, because that would crash when seeing handles created while the
44 // verifier was disabled. This also implies that it is OK if the value change is
45 // not propagated immediately to all CPUs (as would happen with a lock).
46 bool g_verifier_enabled
= true;
48 bool CloseHandleWrapper(HANDLE handle
) {
49 if (!::CloseHandle(handle
))
54 // Simple automatic locking using a native critical section so it supports
56 class AutoNativeLock
{
58 explicit AutoNativeLock(NativeLock
& lock
) : lock_(lock
) {
68 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock
);
77 bool HandleTraits::CloseHandle(HANDLE handle
) {
78 if (!g_verifier_enabled
)
79 return CloseHandleWrapper(handle
);
81 AutoNativeLock
lock(g_lock
.Get());
83 CloseHandleWrapper(handle
);
90 void VerifierTraits::StartTracking(HANDLE handle
, const void* owner
,
91 const void* pc1
, const void* pc2
) {
92 if (!g_verifier_enabled
)
95 // Grab the thread id before the lock.
96 DWORD thread_id
= GetCurrentThreadId();
98 AutoNativeLock
lock(g_lock
.Get());
100 Info handle_info
= { owner
, pc1
, pc2
, thread_id
};
101 std::pair
<HANDLE
, Info
> item(handle
, handle_info
);
102 std::pair
<HandleMap::iterator
, bool> result
= g_handle_map
.Get().insert(item
);
103 if (!result
.second
) {
104 Info other
= result
.first
->second
;
105 debug::Alias(&other
);
111 void VerifierTraits::StopTracking(HANDLE handle
, const void* owner
,
112 const void* pc1
, const void* pc2
) {
113 if (!g_verifier_enabled
)
116 AutoNativeLock
lock(g_lock
.Get());
117 HandleMap::iterator i
= g_handle_map
.Get().find(handle
);
118 if (i
== g_handle_map
.Get().end())
121 Info other
= i
->second
;
122 if (other
.owner
!= owner
) {
123 debug::Alias(&other
);
127 g_handle_map
.Get().erase(i
);
130 void DisableHandleVerifier() {
131 g_verifier_enabled
= false;
134 void OnHandleBeingClosed(HANDLE handle
) {
135 AutoNativeLock
lock(g_lock
.Get());
139 HandleMap::iterator i
= g_handle_map
.Get().find(handle
);
140 if (i
== g_handle_map
.Get().end())
143 Info other
= i
->second
;
144 debug::Alias(&other
);