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

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: Remove stray header 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/hash.h" 10 #include "base/hash.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/synchronization/lock_impl.h" 13 #include "base/synchronization/lock_impl.h"
14 14
15 extern "C" {
16 __declspec(dllexport) void* GetHandleVerifier();
17 typedef void* (*GetHandleVerifierFn)();
18 }
19
15 namespace { 20 namespace {
16 21
17 struct HandleHash { 22 struct HandleHash {
18 size_t operator()(const HANDLE& handle) const { 23 size_t operator()(const HANDLE& handle) const {
19 char buffer[sizeof(handle)]; 24 char buffer[sizeof(handle)];
20 memcpy(buffer, &handle, sizeof(handle)); 25 memcpy(buffer, &handle, sizeof(handle));
21 return base::Hash(buffer, sizeof(buffer)); 26 return base::Hash(buffer, sizeof(buffer));
22 } 27 }
23 }; 28 };
24 29
25 struct Info { 30 struct Info {
26 const void* owner; 31 const void* owner;
27 const void* pc1; 32 const void* pc1;
28 const void* pc2; 33 const void* pc2;
29 DWORD thread_id; 34 DWORD thread_id;
30 }; 35 };
31 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; 36 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap;
32 37
33 // g_lock protects g_handle_map and g_closing. 38 // g_lock protects the handle map and setting g_active_verifier.
34 typedef base::internal::LockImpl NativeLock; 39 typedef base::internal::LockImpl NativeLock;
35 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; 40 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 41
48 bool CloseHandleWrapper(HANDLE handle) { 42 bool CloseHandleWrapper(HANDLE handle) {
49 if (!::CloseHandle(handle)) 43 if (!::CloseHandle(handle))
50 CHECK(false); 44 CHECK(false);
51 return true; 45 return true;
52 } 46 }
53 47
54 // Simple automatic locking using a native critical section so it supports 48 // Simple automatic locking using a native critical section so it supports
55 // recursive locking. 49 // recursive locking.
56 class AutoNativeLock { 50 class AutoNativeLock {
57 public: 51 public:
58 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { 52 explicit AutoNativeLock(NativeLock& lock) : lock_(lock) {
59 lock_.Lock(); 53 lock_.Lock();
60 } 54 }
61 55
62 ~AutoNativeLock() { 56 ~AutoNativeLock() {
63 lock_.Unlock(); 57 lock_.Unlock();
64 } 58 }
65 59
66 private: 60 private:
67 NativeLock& lock_; 61 NativeLock& lock_;
68 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); 62 DISALLOW_COPY_AND_ASSIGN(AutoNativeLock);
69 }; 63 };
70 64
65 // Implements the actual object that is verifying handles for this process.
66 // The active instance is shared across the module boundary but there is no
67 // way to delete this object from the wrong side of it (or any side, actually).
68 class ActiveVerifier {
69 public:
70 explicit ActiveVerifier(bool enabled)
71 : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) {
72 }
73
74 // Retrieves the current verifier.
75 static ActiveVerifier* Get();
76
77 // The methods required by HandleTraits. They are virtual because we need to
78 // forward the call execution to another module, instead of letting the
79 // compiler call the version that is linked in the current module.
80 virtual bool CloseHandle(HANDLE handle);
81 virtual void StartTracking(HANDLE handle, const void* owner,
82 const void* pc1, const void* pc2);
83 virtual void StopTracking(HANDLE handle, const void* owner,
84 const void* pc1, const void* pc2);
85 virtual void Disable();
86 virtual void OnHandleBeingClosed(HANDLE handle);
87
88 private:
89 ~ActiveVerifier(); // Not implemented.
90
91 static void InstallVerifier();
92
93 bool enabled_;
94 bool closing_;
95 NativeLock* lock_;
96 HandleMap map_;
97 DISALLOW_COPY_AND_ASSIGN(ActiveVerifier);
98 };
99 ActiveVerifier* g_active_verifier = NULL;
100
101 // static
102 ActiveVerifier* ActiveVerifier::Get() {
103 if (!g_active_verifier)
104 ActiveVerifier::InstallVerifier();
105
106 return g_active_verifier;
107 }
108
109 // static
110 void ActiveVerifier::InstallVerifier() {
111 #if defined(COMPONENT_BUILD)
112 AutoNativeLock lock(g_lock.Get());
113 g_active_verifier = new ActiveVerifier(true);
114 #else
115 // If you are reading this, wondering why your process seems deadlocked, take
116 // a look at your DllMain code and remove things that should not be done
117 // there, like doing whatever gave you that nice windows handle you are trying
118 // to store in a ScopedHandle.
119 HMODULE main_module = ::GetModuleHandle(NULL);
120 GetHandleVerifierFn get_handle_verifier =
121 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
122 main_module, "GetHandleVerifier"));
123
124 if (!get_handle_verifier) {
125 g_active_verifier = new ActiveVerifier(false);
126 return;
127 }
128
129 ActiveVerifier* verifier =
130 reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
131
132 // This lock only protects against races in this module, which is fine.
133 AutoNativeLock lock(g_lock.Get());
134 g_active_verifier = verifier ? verifier : new ActiveVerifier(true);
135 #endif
136 }
137
138 bool ActiveVerifier::CloseHandle(HANDLE handle) {
139 if (!enabled_)
140 return CloseHandleWrapper(handle);
141
142 AutoNativeLock lock(*lock_);
143 closing_ = true;
144 CloseHandleWrapper(handle);
145 closing_ = false;
146
147 return true;
148 }
149
150 void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
151 const void* pc1, const void* pc2) {
152 if (!enabled_)
153 return;
154
155 // Grab the thread id before the lock.
156 DWORD thread_id = GetCurrentThreadId();
157
158 AutoNativeLock lock(*lock_);
159
160 Info handle_info = { owner, pc1, pc2, thread_id };
161 std::pair<HANDLE, Info> item(handle, handle_info);
162 std::pair<HandleMap::iterator, bool> result = map_.insert(item);
163 if (!result.second) {
164 Info other = result.first->second;
165 base::debug::Alias(&other);
166 CHECK(false);
167 }
168 }
169
170 void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
171 const void* pc1, const void* pc2) {
172 if (!enabled_)
173 return;
174
175 AutoNativeLock lock(*lock_);
176 HandleMap::iterator i = map_.find(handle);
177 if (i == map_.end())
178 CHECK(false);
179
180 Info other = i->second;
181 if (other.owner != owner) {
182 base::debug::Alias(&other);
183 CHECK(false);
184 }
185
186 map_.erase(i);
187 }
188
189 void ActiveVerifier::Disable() {
190 enabled_ = false;
191 }
192
193 void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
194 AutoNativeLock lock(*lock_);
195 if (closing_)
196 return;
197
198 HandleMap::iterator i = map_.find(handle);
199 if (i == map_.end())
200 return;
201
202 Info other = i->second;
203 base::debug::Alias(&other);
204 CHECK(false);
205 }
206
71 } // namespace 207 } // namespace
72 208
209 void* GetHandleVerifier() {
210 return g_active_verifier;
211 }
212
73 namespace base { 213 namespace base {
74 namespace win { 214 namespace win {
75 215
76 // Static. 216 // Static.
77 bool HandleTraits::CloseHandle(HANDLE handle) { 217 bool HandleTraits::CloseHandle(HANDLE handle) {
78 if (!g_verifier_enabled) 218 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 } 219 }
88 220
89 // Static. 221 // Static.
90 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, 222 void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
91 const void* pc1, const void* pc2) { 223 const void* pc1, const void* pc2) {
92 if (!g_verifier_enabled) 224 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 } 225 }
109 226
110 // Static. 227 // Static.
111 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, 228 void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
112 const void* pc1, const void* pc2) { 229 const void* pc1, const void* pc2) {
113 if (!g_verifier_enabled) 230 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 } 231 }
129 232
130 void DisableHandleVerifier() { 233 void DisableHandleVerifier() {
131 g_verifier_enabled = false; 234 return ActiveVerifier::Get()->Disable();
132 } 235 }
133 236
134 void OnHandleBeingClosed(HANDLE handle) { 237 void OnHandleBeingClosed(HANDLE handle) {
135 AutoNativeLock lock(g_lock.Get()); 238 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 } 239 }
147 240
148 } // namespace win 241 } // namespace win
149 } // namespace base 242 } // 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