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 "base/containers/hash_tables.h" | 7 #include <map> |
| 8 |
8 #include "base/debug/alias.h" | 9 #include "base/debug/alias.h" |
9 #include "base/hash.h" | |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "base/logging.h" | 11 #include "base/synchronization/lock.h" |
12 #include "base/synchronization/lock_impl.h" | |
13 #include "base/win/windows_version.h" | 12 #include "base/win/windows_version.h" |
14 | 13 |
15 namespace { | 14 namespace { |
16 | 15 |
17 struct Info { | 16 struct Info { |
18 const void* owner; | 17 const void* owner; |
19 const void* pc1; | 18 const void* pc1; |
20 const void* pc2; | 19 const void* pc2; |
21 DWORD thread_id; | 20 DWORD thread_id; |
22 }; | 21 }; |
23 typedef base::hash_map<HANDLE, Info> HandleMap; | 22 typedef std::map<HANDLE, Info> HandleMap; |
24 | 23 |
25 typedef base::internal::LockImpl NativeLock; | |
26 base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER; | 24 base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER; |
27 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; | 25 base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; |
28 bool g_closing = false; | |
29 bool g_verifier_enabled = false; | |
30 | |
31 bool CloseHandleWrapper(HANDLE handle) { | |
32 if (!::CloseHandle(handle)) | |
33 CHECK(false); | |
34 return true; | |
35 } | |
36 | |
37 // Simple automatic locking using a native critical section so it supports | |
38 // recursive locking. | |
39 class AutoNativeLock { | |
40 public: | |
41 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { | |
42 lock_.Lock(); | |
43 } | |
44 | |
45 ~AutoNativeLock() { | |
46 lock_.Unlock(); | |
47 } | |
48 | |
49 private: | |
50 NativeLock& lock_; | |
51 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); | |
52 }; | |
53 | |
54 inline size_t HashHandle(const HANDLE& handle) { | |
55 char buffer[sizeof(handle)]; | |
56 memcpy(buffer, &handle, sizeof(handle)); | |
57 return base::Hash(buffer, sizeof(buffer)); | |
58 } | |
59 | 26 |
60 } // namespace | 27 } // namespace |
61 | 28 |
62 namespace BASE_HASH_NAMESPACE { | |
63 #if defined(COMPILER_MSVC) | |
64 inline size_t hash_value(const HANDLE& handle) { | |
65 return HashHandle(handle); | |
66 } | |
67 #elif defined (COMPILER_GCC) | |
68 template <> | |
69 struct hash<HANDLE> { | |
70 size_t operator()(const HANDLE& handle) const { | |
71 return HashHandle(handle); | |
72 } | |
73 }; | |
74 #endif | |
75 } // BASE_HASH_NAMESPACE | |
76 | |
77 namespace base { | 29 namespace base { |
78 namespace win { | 30 namespace win { |
79 | 31 |
80 // Static. | 32 // Static. |
81 bool HandleTraits::CloseHandle(HANDLE handle) { | |
82 if (!g_verifier_enabled) | |
83 return CloseHandleWrapper(handle); | |
84 | |
85 AutoNativeLock lock(g_lock.Get()); | |
86 g_closing = true; | |
87 CloseHandleWrapper(handle); | |
88 g_closing = false; | |
89 | |
90 return true; | |
91 } | |
92 | |
93 // Static. | |
94 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, | 33 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, |
95 const void* pc1, const void* pc2) { | 34 const void* pc1, const void* pc2) { |
96 if (!g_verifier_enabled) | |
97 return; | |
98 | |
99 // Grab the thread id before the lock. | 35 // Grab the thread id before the lock. |
100 DWORD thread_id = GetCurrentThreadId(); | 36 DWORD thread_id = GetCurrentThreadId(); |
101 | 37 |
102 AutoNativeLock lock(g_lock.Get()); | 38 AutoLock lock(g_lock.Get()); |
103 | 39 |
104 Info handle_info = { owner, pc1, pc2, thread_id }; | 40 Info handle_info = { owner, pc1, pc2, thread_id }; |
105 std::pair<HANDLE, Info> item(handle, handle_info); | 41 std::pair<HANDLE, Info> item(handle, handle_info); |
106 std::pair<HandleMap::iterator, bool> result = g_handle_map.Get().insert(item); | 42 std::pair<HandleMap::iterator, bool> result = g_handle_map.Get().insert(item); |
107 if (!result.second) { | 43 if (!result.second) { |
108 Info other = result.first->second; | 44 Info other = result.first->second; |
109 debug::Alias(&other); | 45 debug::Alias(&other); |
110 CHECK(false); | 46 CHECK(false); |
111 } | 47 } |
112 } | 48 } |
113 | 49 |
114 // Static. | 50 // Static. |
115 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, | 51 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, |
116 const void* pc1, const void* pc2) { | 52 const void* pc1, const void* pc2) { |
117 if (!g_verifier_enabled) | 53 AutoLock lock(g_lock.Get()); |
118 return; | |
119 | |
120 AutoNativeLock lock(g_lock.Get()); | |
121 HandleMap::iterator i = g_handle_map.Get().find(handle); | 54 HandleMap::iterator i = g_handle_map.Get().find(handle); |
122 if (i == g_handle_map.Get().end()) | 55 if (i == g_handle_map.Get().end()) |
123 CHECK(false); | 56 CHECK(false); |
124 | 57 |
125 Info other = i->second; | 58 Info other = i->second; |
126 if (other.owner != owner) { | 59 if (other.owner != owner) { |
127 debug::Alias(&other); | 60 debug::Alias(&other); |
128 CHECK(false); | 61 CHECK(false); |
129 } | 62 } |
130 | 63 |
131 g_handle_map.Get().erase(i); | 64 g_handle_map.Get().erase(i); |
132 } | 65 } |
133 | 66 |
134 void EnableHandleVerifier() { | |
135 g_verifier_enabled = true; | |
136 } | |
137 | |
138 void OnHandleBeingClosed(HANDLE handle) { | |
139 AutoNativeLock lock(g_lock.Get()); | |
140 if (g_closing) | |
141 return; | |
142 | |
143 HandleMap::iterator i = g_handle_map.Get().find(handle); | |
144 if (i == g_handle_map.Get().end()) | |
145 return; | |
146 | |
147 Info other = i->second; | |
148 debug::Alias(&other); | |
149 CHECK(false); | |
150 } | |
151 | |
152 } // namespace win | 67 } // namespace win |
153 } // namespace base | 68 } // namespace base |
OLD | NEW |