Chromium Code Reviews| Index: base/win/scoped_handle.cc |
| diff --git a/base/win/scoped_handle.cc b/base/win/scoped_handle.cc |
| index 7b38369d5aa2706a8f7469f994ed1c1d48801846..2934daa2150029c701d6d36eeef14827033c5573 100644 |
| --- a/base/win/scoped_handle.cc |
| +++ b/base/win/scoped_handle.cc |
| @@ -4,25 +4,60 @@ |
| #include "base/win/scoped_handle.h" |
| -#include <map> |
| +#include <unordered_map> |
| #include "base/debug/alias.h" |
| +#include "base/hash.h" |
| #include "base/lazy_instance.h" |
| -#include "base/synchronization/lock.h" |
| -#include "base/win/windows_version.h" |
| +#include "base/logging.h" |
| +#include "base/synchronization/lock_impl.h" |
| namespace { |
| +struct HandleHash { |
| + size_t operator()(const HANDLE& handle) const { |
| + char buffer[sizeof(handle)]; |
| + memcpy(buffer, &handle, sizeof(handle)); |
| + return base::Hash(buffer, sizeof(buffer)); |
| + } |
| +}; |
| + |
| struct Info { |
| const void* owner; |
| const void* pc1; |
| const void* pc2; |
| DWORD thread_id; |
| }; |
| -typedef std::map<HANDLE, Info> HandleMap; |
| +typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; |
| +typedef base::internal::LockImpl NativeLock; |
| base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER; |
| -base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; |
| +base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; |
| +bool g_closing = false; |
| +bool g_verifier_enabled = true; |
| + |
| +bool CloseHandleWrapper(HANDLE handle) { |
| + if (!::CloseHandle(handle)) |
| + CHECK(false); |
| + return true; |
| +} |
| + |
| +// Simple automatic locking using a native critical section so it supports |
| +// recursive locking. |
| +class AutoNativeLock { |
| + public: |
| + explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { |
| + lock_.Lock(); |
| + } |
| + |
| + ~AutoNativeLock() { |
| + lock_.Unlock(); |
| + } |
| + |
| + private: |
| + NativeLock& lock_; |
| + DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); |
| +}; |
| } // namespace |
| @@ -30,12 +65,28 @@ namespace base { |
| namespace win { |
| // Static. |
| +bool HandleTraits::CloseHandle(HANDLE handle) { |
| + if (!g_verifier_enabled) |
| + return CloseHandleWrapper(handle); |
| + |
| + AutoNativeLock lock(g_lock.Get()); |
| + g_closing = true; |
| + CloseHandleWrapper(handle); |
| + g_closing = false; |
| + |
| + return true; |
| +} |
| + |
| +// Static. |
| void VerifierTraits::StartTracking(HANDLE handle, const void* owner, |
| const void* pc1, const void* pc2) { |
| + if (!g_verifier_enabled) |
| + return; |
| + |
| // Grab the thread id before the lock. |
| DWORD thread_id = GetCurrentThreadId(); |
| - AutoLock lock(g_lock.Get()); |
| + AutoNativeLock lock(g_lock.Get()); |
| Info handle_info = { owner, pc1, pc2, thread_id }; |
| std::pair<HANDLE, Info> item(handle, handle_info); |
| @@ -50,7 +101,10 @@ void VerifierTraits::StartTracking(HANDLE handle, const void* owner, |
| // Static. |
| void VerifierTraits::StopTracking(HANDLE handle, const void* owner, |
| const void* pc1, const void* pc2) { |
| - AutoLock lock(g_lock.Get()); |
| + if (!g_verifier_enabled) |
| + return; |
| + |
| + AutoNativeLock lock(g_lock.Get()); |
| HandleMap::iterator i = g_handle_map.Get().find(handle); |
| if (i == g_handle_map.Get().end()) |
| CHECK(false); |
| @@ -64,5 +118,23 @@ void VerifierTraits::StopTracking(HANDLE handle, const void* owner, |
| g_handle_map.Get().erase(i); |
| } |
| +void DisableHandleVerifier() { |
| + g_verifier_enabled = false; |
|
cpu_(ooo_6.6-7.5)
2014/09/03 22:10:14
a note above 121 as of why g_verifier_enabled is n
|
| +} |
| + |
| +void OnHandleBeingClosed(HANDLE handle) { |
| + AutoNativeLock lock(g_lock.Get()); |
| + if (g_closing) |
| + return; |
| + |
| + HandleMap::iterator i = g_handle_map.Get().find(handle); |
| + if (i == g_handle_map.Get().end()) |
| + return; |
| + |
| + Info other = i->second; |
| + debug::Alias(&other); |
| + CHECK(false); |
| +} |
| + |
| } // namespace win |
| } // namespace base |