OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/win/scoped_handle.h" | 5 #include "base/win/scoped_handle.h" |
6 | 6 |
7 #include <unordered_map> | 7 #include <unordered_map> |
8 | 8 |
9 #include "base/debug/alias.h" | 9 #include "base/debug/alias.h" |
10 #include "base/hash.h" | 10 #include "base/hash.h" |
11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/synchronization/lock_impl.h" | 13 #include "base/synchronization/lock_impl.h" |
14 | 14 |
| 15 extern "C" { |
| 16 __declspec(dllexport) void* GetHandleVerifier(); |
| 17 typedef void* (*GetHandleVerifierFn)(); |
| 18 } |
| 19 |
15 namespace { | 20 namespace { |
16 | 21 |
17 struct HandleHash { | 22 struct HandleHash { |
18 size_t operator()(const HANDLE& handle) const { | 23 size_t operator()(const HANDLE& handle) const { |
19 char buffer[sizeof(handle)]; | 24 char buffer[sizeof(handle)]; |
20 memcpy(buffer, &handle, sizeof(handle)); | 25 memcpy(buffer, &handle, sizeof(handle)); |
21 return base::Hash(buffer, sizeof(buffer)); | 26 return base::Hash(buffer, sizeof(buffer)); |
22 } | 27 } |
23 }; | 28 }; |
24 | 29 |
25 struct Info { | 30 struct Info { |
26 const void* owner; | 31 const void* owner; |
27 const void* pc1; | 32 const void* pc1; |
28 const void* pc2; | 33 const void* pc2; |
29 DWORD thread_id; | 34 DWORD thread_id; |
30 }; | 35 }; |
31 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; | 36 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; |
32 | 37 |
33 // g_lock protects g_handle_map and g_closing. | 38 // g_lock protects the handle map and setting g_active_verifier. |
34 typedef base::internal::LockImpl NativeLock; | 39 typedef base::internal::LockImpl NativeLock; |
35 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; | 40 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; | |
38 | |
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; | |
47 | 41 |
48 bool CloseHandleWrapper(HANDLE handle) { | 42 bool CloseHandleWrapper(HANDLE handle) { |
49 if (!::CloseHandle(handle)) | 43 if (!::CloseHandle(handle)) |
50 CHECK(false); | 44 CHECK(false); |
51 return true; | 45 return true; |
52 } | 46 } |
53 | 47 |
54 // Simple automatic locking using a native critical section so it supports | 48 // Simple automatic locking using a native critical section so it supports |
55 // recursive locking. | 49 // recursive locking. |
56 class AutoNativeLock { | 50 class AutoNativeLock { |
57 public: | 51 public: |
58 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { | 52 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { |
59 lock_.Lock(); | 53 lock_.Lock(); |
60 } | 54 } |
61 | 55 |
62 ~AutoNativeLock() { | 56 ~AutoNativeLock() { |
63 lock_.Unlock(); | 57 lock_.Unlock(); |
64 } | 58 } |
65 | 59 |
66 private: | 60 private: |
67 NativeLock& lock_; | 61 NativeLock& lock_; |
68 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); | 62 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); |
69 }; | 63 }; |
70 | 64 |
| 65 // Implements the actual object that is verifying handles for this process. |
| 66 // The active instance is shared across the module boundary but there is no |
| 67 // way to delete this object from the wrong side of it (or any side, actually). |
| 68 class ActiveVerifier { |
| 69 public: |
| 70 explicit ActiveVerifier(bool enabled) |
| 71 : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) { |
| 72 } |
| 73 |
| 74 // Retrieves the current verifier. |
| 75 static ActiveVerifier* Get(); |
| 76 |
| 77 // The methods required by HandleTraits. They are virtual because we need to |
| 78 // forward the call execution to another module, instead of letting the |
| 79 // compiler call the version that is linked in the current module. |
| 80 virtual bool CloseHandle(HANDLE handle); |
| 81 virtual void StartTracking(HANDLE handle, const void* owner, |
| 82 const void* pc1, const void* pc2); |
| 83 virtual void StopTracking(HANDLE handle, const void* owner, |
| 84 const void* pc1, const void* pc2); |
| 85 virtual void Disable(); |
| 86 virtual void OnHandleBeingClosed(HANDLE handle); |
| 87 |
| 88 private: |
| 89 ~ActiveVerifier(); // Not implemented. |
| 90 |
| 91 static void InstallVerifier(); |
| 92 |
| 93 bool enabled_; |
| 94 bool closing_; |
| 95 NativeLock* lock_; |
| 96 HandleMap map_; |
| 97 DISALLOW_COPY_AND_ASSIGN(ActiveVerifier); |
| 98 }; |
| 99 ActiveVerifier* g_active_verifier = NULL; |
| 100 |
| 101 // static |
| 102 ActiveVerifier* ActiveVerifier::Get() { |
| 103 if (!g_active_verifier) |
| 104 ActiveVerifier::InstallVerifier(); |
| 105 |
| 106 return g_active_verifier; |
| 107 } |
| 108 |
| 109 // static |
| 110 void ActiveVerifier::InstallVerifier() { |
| 111 #if defined(COMPONENT_BUILD) |
| 112 AutoNativeLock lock(g_lock.Get()); |
| 113 g_active_verifier = new ActiveVerifier(true); |
| 114 #else |
| 115 // If you are reading this, wondering why your process seems deadlocked, take |
| 116 // a look at your DllMain code and remove things that should not be done |
| 117 // there, like doing whatever gave you that nice windows handle you are trying |
| 118 // to store in a ScopedHandle. |
| 119 HMODULE main_module = ::GetModuleHandle(NULL); |
| 120 GetHandleVerifierFn get_handle_verifier = |
| 121 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress( |
| 122 main_module, "GetHandleVerifier")); |
| 123 |
| 124 if (!get_handle_verifier) { |
| 125 g_active_verifier = new ActiveVerifier(false); |
| 126 return; |
| 127 } |
| 128 |
| 129 ActiveVerifier* verifier = |
| 130 reinterpret_cast<ActiveVerifier*>(get_handle_verifier()); |
| 131 |
| 132 // This lock only protects against races in this module, which is fine. |
| 133 AutoNativeLock lock(g_lock.Get()); |
| 134 g_active_verifier = verifier ? verifier : new ActiveVerifier(true); |
| 135 #endif |
| 136 } |
| 137 |
| 138 bool ActiveVerifier::CloseHandle(HANDLE handle) { |
| 139 if (!enabled_) |
| 140 return CloseHandleWrapper(handle); |
| 141 |
| 142 AutoNativeLock lock(*lock_); |
| 143 closing_ = true; |
| 144 CloseHandleWrapper(handle); |
| 145 closing_ = false; |
| 146 |
| 147 return true; |
| 148 } |
| 149 |
| 150 void ActiveVerifier::StartTracking(HANDLE handle, const void* owner, |
| 151 const void* pc1, const void* pc2) { |
| 152 if (!enabled_) |
| 153 return; |
| 154 |
| 155 // Grab the thread id before the lock. |
| 156 DWORD thread_id = GetCurrentThreadId(); |
| 157 |
| 158 AutoNativeLock lock(*lock_); |
| 159 |
| 160 Info handle_info = { owner, pc1, pc2, thread_id }; |
| 161 std::pair<HANDLE, Info> item(handle, handle_info); |
| 162 std::pair<HandleMap::iterator, bool> result = map_.insert(item); |
| 163 if (!result.second) { |
| 164 Info other = result.first->second; |
| 165 base::debug::Alias(&other); |
| 166 CHECK(false); |
| 167 } |
| 168 } |
| 169 |
| 170 void ActiveVerifier::StopTracking(HANDLE handle, const void* owner, |
| 171 const void* pc1, const void* pc2) { |
| 172 if (!enabled_) |
| 173 return; |
| 174 |
| 175 AutoNativeLock lock(*lock_); |
| 176 HandleMap::iterator i = map_.find(handle); |
| 177 if (i == map_.end()) |
| 178 CHECK(false); |
| 179 |
| 180 Info other = i->second; |
| 181 if (other.owner != owner) { |
| 182 base::debug::Alias(&other); |
| 183 CHECK(false); |
| 184 } |
| 185 |
| 186 map_.erase(i); |
| 187 } |
| 188 |
| 189 void ActiveVerifier::Disable() { |
| 190 enabled_ = false; |
| 191 } |
| 192 |
| 193 void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) { |
| 194 AutoNativeLock lock(*lock_); |
| 195 if (closing_) |
| 196 return; |
| 197 |
| 198 HandleMap::iterator i = map_.find(handle); |
| 199 if (i == map_.end()) |
| 200 return; |
| 201 |
| 202 Info other = i->second; |
| 203 base::debug::Alias(&other); |
| 204 CHECK(false); |
| 205 } |
| 206 |
71 } // namespace | 207 } // namespace |
72 | 208 |
| 209 void* GetHandleVerifier() { |
| 210 return g_active_verifier; |
| 211 } |
| 212 |
73 namespace base { | 213 namespace base { |
74 namespace win { | 214 namespace win { |
75 | 215 |
76 // Static. | 216 // Static. |
77 bool HandleTraits::CloseHandle(HANDLE handle) { | 217 bool HandleTraits::CloseHandle(HANDLE handle) { |
78 if (!g_verifier_enabled) | 218 return ActiveVerifier::Get()->CloseHandle(handle); |
79 return CloseHandleWrapper(handle); | |
80 | |
81 AutoNativeLock lock(g_lock.Get()); | |
82 g_closing = true; | |
83 CloseHandleWrapper(handle); | |
84 g_closing = false; | |
85 | |
86 return true; | |
87 } | 219 } |
88 | 220 |
89 // Static. | 221 // Static. |
90 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, | 222 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, |
91 const void* pc1, const void* pc2) { | 223 const void* pc1, const void* pc2) { |
92 if (!g_verifier_enabled) | 224 return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2); |
93 return; | |
94 | |
95 // Grab the thread id before the lock. | |
96 DWORD thread_id = GetCurrentThreadId(); | |
97 | |
98 AutoNativeLock lock(g_lock.Get()); | |
99 | |
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); | |
106 CHECK(false); | |
107 } | |
108 } | 225 } |
109 | 226 |
110 // Static. | 227 // Static. |
111 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, | 228 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, |
112 const void* pc1, const void* pc2) { | 229 const void* pc1, const void* pc2) { |
113 if (!g_verifier_enabled) | 230 return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2); |
114 return; | |
115 | |
116 AutoNativeLock lock(g_lock.Get()); | |
117 HandleMap::iterator i = g_handle_map.Get().find(handle); | |
118 if (i == g_handle_map.Get().end()) | |
119 CHECK(false); | |
120 | |
121 Info other = i->second; | |
122 if (other.owner != owner) { | |
123 debug::Alias(&other); | |
124 CHECK(false); | |
125 } | |
126 | |
127 g_handle_map.Get().erase(i); | |
128 } | 231 } |
129 | 232 |
130 void DisableHandleVerifier() { | 233 void DisableHandleVerifier() { |
131 g_verifier_enabled = false; | 234 return ActiveVerifier::Get()->Disable(); |
132 } | 235 } |
133 | 236 |
134 void OnHandleBeingClosed(HANDLE handle) { | 237 void OnHandleBeingClosed(HANDLE handle) { |
135 AutoNativeLock lock(g_lock.Get()); | 238 return ActiveVerifier::Get()->OnHandleBeingClosed(handle); |
136 if (g_closing) | |
137 return; | |
138 | |
139 HandleMap::iterator i = g_handle_map.Get().find(handle); | |
140 if (i == g_handle_map.Get().end()) | |
141 return; | |
142 | |
143 Info other = i->second; | |
144 debug::Alias(&other); | |
145 CHECK(false); | |
146 } | 239 } |
147 | 240 |
148 } // namespace win | 241 } // namespace win |
149 } // namespace base | 242 } // namespace base |
OLD | NEW |