Chromium Code Reviews| 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> |
|
grt (UTC plus 2)
2015/04/01 15:33:04
would you mind switching from unordered_map to "ba
rvargas (doing something else)
2015/04/01 16:51:03
This was used here because of inconsistencies in o
grt (UTC plus 2)
2015/04/01 20:33:02
That ain't good.
| |
| 8 | 8 |
| 9 #include "base/debug/alias.h" | 9 #include "base/debug/alias.h" |
| 10 #include "base/environment.h" | |
| 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 ActiveVerifier(bool enabled) | |
|
grt (UTC plus 2)
2015/04/01 15:33:04
explicit
rvargas (doing something else)
2015/04/01 16:51:03
Acknowledged.
| |
| 72 : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) { | |
| 73 } | |
| 74 | |
| 75 static void InstallVerifier(); | |
| 76 | |
| 77 // The methods required by HandleTraits: | |
| 78 virtual bool CloseHandle(HANDLE handle); | |
|
grt (UTC plus 2)
2015/04/01 15:33:04
why virtual? if it's for a subtle "because we need
rvargas (doing something else)
2015/04/01 16:51:03
Yes the whole point of the CL is that we need to f
grt (UTC plus 2)
2015/04/01 20:33:02
Yup, that's what I thought.
grt (UTC plus 2)
2015/04/02 02:19:03
Wait, why is that necessary? Are not all modules t
rvargas (doing something else)
2015/04/02 17:53:57
Sortof. All the state is inside the object, but th
| |
| 79 virtual void StartTracking(HANDLE handle, const void* owner, | |
| 80 const void* pc1, const void* pc2); | |
| 81 virtual void StopTracking(HANDLE handle, const void* owner, | |
| 82 const void* pc1, const void* pc2); | |
| 83 virtual void Disable(); | |
| 84 virtual void OnHandleBeingClosed(HANDLE handle); | |
| 85 | |
| 86 private: | |
| 87 ~ActiveVerifier(); | |
|
grt (UTC plus 2)
2015/04/01 15:33:04
if the methods above truly need to be virtual, mak
rvargas (doing something else)
2015/04/01 16:51:03
There's no destructor implementation.
grt (UTC plus 2)
2015/04/01 20:33:02
Ah, so there isn't. Ack.
| |
| 88 | |
| 89 bool enabled_; | |
| 90 bool closing_; | |
| 91 NativeLock* lock_; | |
| 92 HandleMap map_; | |
| 93 DISALLOW_COPY_AND_ASSIGN(ActiveVerifier); | |
| 94 }; | |
| 95 ActiveVerifier* g_active_verifier = NULL; | |
| 96 | |
| 97 // static | |
| 98 void ActiveVerifier::InstallVerifier() { | |
| 99 #if defined(COMPONENT_BUILD) | |
| 100 AutoNativeLock lock(g_lock.Get()); | |
| 101 g_active_verifier = new ActiveVerifier(true); | |
| 102 #else | |
| 103 HMODULE main_module = ::GetModuleHandle(NULL); | |
| 104 GetHandleVerifierFn get_handle_verifier = | |
| 105 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress( | |
| 106 main_module, "GetHandleVerifier")); | |
| 107 | |
| 108 if (!get_handle_verifier) { | |
| 109 g_active_verifier = new ActiveVerifier(false); | |
|
grt (UTC plus 2)
2015/04/01 15:33:04
indentation
rvargas (doing something else)
2015/04/01 16:51:03
... I saw that while testing and I forgot to fix i
| |
| 110 return; | |
| 111 } | |
| 112 | |
| 113 ActiveVerifier* verifier = | |
| 114 reinterpret_cast<ActiveVerifier*>(get_handle_verifier()); | |
| 115 | |
| 116 AutoNativeLock lock(g_lock.Get()); | |
| 117 g_active_verifier = verifier ? verifier : new ActiveVerifier(true); | |
| 118 #endif | |
| 119 } | |
| 120 | |
| 121 bool ActiveVerifier::CloseHandle(HANDLE handle) { | |
| 122 if (!enabled_) | |
| 123 return CloseHandleWrapper(handle); | |
| 124 | |
| 125 AutoNativeLock lock(*lock_); | |
| 126 closing_ = true; | |
| 127 CloseHandleWrapper(handle); | |
| 128 closing_ = false; | |
| 129 | |
| 130 return true; | |
| 131 } | |
| 132 | |
| 133 void ActiveVerifier::StartTracking(HANDLE handle, const void* owner, | |
| 134 const void* pc1, const void* pc2) { | |
| 135 if (!enabled_) | |
| 136 return; | |
| 137 | |
| 138 // Grab the thread id before the lock. | |
| 139 DWORD thread_id = GetCurrentThreadId(); | |
| 140 | |
| 141 AutoNativeLock lock(*lock_); | |
| 142 | |
| 143 Info handle_info = { owner, pc1, pc2, thread_id }; | |
| 144 std::pair<HANDLE, Info> item(handle, handle_info); | |
| 145 std::pair<HandleMap::iterator, bool> result = map_.insert(item); | |
| 146 if (!result.second) { | |
| 147 Info other = result.first->second; | |
| 148 base::debug::Alias(&other); | |
| 149 CHECK(false); | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 void ActiveVerifier::StopTracking(HANDLE handle, const void* owner, | |
| 154 const void* pc1, const void* pc2) { | |
| 155 if (!enabled_) | |
| 156 return; | |
| 157 | |
| 158 AutoNativeLock lock(*lock_); | |
| 159 HandleMap::iterator i = map_.find(handle); | |
| 160 if (i == map_.end()) | |
| 161 CHECK(false); | |
| 162 | |
| 163 Info other = i->second; | |
| 164 if (other.owner != owner) { | |
| 165 base::debug::Alias(&other); | |
| 166 CHECK(false); | |
| 167 } | |
| 168 | |
| 169 map_.erase(i); | |
| 170 } | |
| 171 | |
| 172 void ActiveVerifier::Disable() { | |
| 173 enabled_ = false; | |
| 174 } | |
| 175 | |
| 176 void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) { | |
| 177 AutoNativeLock lock(*lock_); | |
| 178 if (closing_) | |
| 179 return; | |
| 180 | |
| 181 HandleMap::iterator i = map_.find(handle); | |
| 182 if (i == map_.end()) | |
| 183 return; | |
| 184 | |
| 185 Info other = i->second; | |
| 186 base::debug::Alias(&other); | |
| 187 CHECK(false); | |
| 188 } | |
| 189 | |
| 71 } // namespace | 190 } // namespace |
| 72 | 191 |
| 192 void* GetHandleVerifier() { | |
| 193 return g_active_verifier; | |
| 194 } | |
| 195 | |
| 73 namespace base { | 196 namespace base { |
| 74 namespace win { | 197 namespace win { |
| 75 | 198 |
| 76 // Static. | 199 // Static. |
| 77 bool HandleTraits::CloseHandle(HANDLE handle) { | 200 bool HandleTraits::CloseHandle(HANDLE handle) { |
| 78 if (!g_verifier_enabled) | 201 if (!g_active_verifier) |
| 79 return CloseHandleWrapper(handle); | 202 ActiveVerifier::InstallVerifier(); |
| 80 | 203 |
| 81 AutoNativeLock lock(g_lock.Get()); | 204 return g_active_verifier->CloseHandle(handle); |
| 82 g_closing = true; | |
| 83 CloseHandleWrapper(handle); | |
| 84 g_closing = false; | |
| 85 | |
| 86 return true; | |
| 87 } | 205 } |
| 88 | 206 |
| 89 // Static. | 207 // Static. |
| 90 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, | 208 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, |
| 91 const void* pc1, const void* pc2) { | 209 const void* pc1, const void* pc2) { |
| 92 if (!g_verifier_enabled) | 210 if (!g_active_verifier) |
| 93 return; | 211 ActiveVerifier::InstallVerifier(); |
| 94 | 212 |
| 95 // Grab the thread id before the lock. | 213 return g_active_verifier->StartTracking(handle, owner, pc1, pc2); |
| 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 } | 214 } |
| 109 | 215 |
| 110 // Static. | 216 // Static. |
| 111 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, | 217 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, |
| 112 const void* pc1, const void* pc2) { | 218 const void* pc1, const void* pc2) { |
| 113 if (!g_verifier_enabled) | 219 if (!g_active_verifier) |
| 114 return; | 220 ActiveVerifier::InstallVerifier(); |
| 115 | 221 |
| 116 AutoNativeLock lock(g_lock.Get()); | 222 return g_active_verifier->StopTracking(handle, owner, pc1, pc2); |
| 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 } | 223 } |
| 129 | 224 |
| 130 void DisableHandleVerifier() { | 225 void DisableHandleVerifier() { |
| 131 g_verifier_enabled = false; | 226 if (!g_active_verifier) |
| 227 ActiveVerifier::InstallVerifier(); | |
| 228 | |
| 229 return g_active_verifier->Disable(); | |
| 132 } | 230 } |
| 133 | 231 |
| 134 void OnHandleBeingClosed(HANDLE handle) { | 232 void OnHandleBeingClosed(HANDLE handle) { |
| 135 AutoNativeLock lock(g_lock.Get()); | 233 if (!g_active_verifier) |
| 136 if (g_closing) | 234 ActiveVerifier::InstallVerifier(); |
| 137 return; | |
| 138 | 235 |
| 139 HandleMap::iterator i = g_handle_map.Get().find(handle); | 236 return g_active_verifier->OnHandleBeingClosed(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 } | 237 } |
| 147 | 238 |
| 148 } // namespace win | 239 } // namespace win |
| 149 } // namespace base | 240 } // namespace base |
| OLD | NEW |