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> |
| 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 |