Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: base/win/scoped_handle.cc

Issue 1045513004: Integrate the handle verifier from multiple modules (DLLs) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Now with more comments Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698