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