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

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: GetProcAddress 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>
grt (UTC plus 2) 2015/04/01 15:33:04 would you mind switching from unordered_map to "ba
rvargas (doing something else) 2015/04/01 16:51:03 This was used here because of inconsistencies in o
grt (UTC plus 2) 2015/04/01 20:33:02 That ain't good.
8 8
9 #include "base/debug/alias.h" 9 #include "base/debug/alias.h"
10 #include "base/environment.h"
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 ActiveVerifier(bool enabled)
grt (UTC plus 2) 2015/04/01 15:33:04 explicit
rvargas (doing something else) 2015/04/01 16:51:03 Acknowledged.
72 : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) {
73 }
74
75 static void InstallVerifier();
76
77 // The methods required by HandleTraits:
78 virtual bool CloseHandle(HANDLE handle);
grt (UTC plus 2) 2015/04/01 15:33:04 why virtual? if it's for a subtle "because we need
rvargas (doing something else) 2015/04/01 16:51:03 Yes the whole point of the CL is that we need to f
grt (UTC plus 2) 2015/04/01 20:33:02 Yup, that's what I thought.
grt (UTC plus 2) 2015/04/02 02:19:03 Wait, why is that necessary? Are not all modules t
rvargas (doing something else) 2015/04/02 17:53:57 Sortof. All the state is inside the object, but th
79 virtual void StartTracking(HANDLE handle, const void* owner,
80 const void* pc1, const void* pc2);
81 virtual void StopTracking(HANDLE handle, const void* owner,
82 const void* pc1, const void* pc2);
83 virtual void Disable();
84 virtual void OnHandleBeingClosed(HANDLE handle);
85
86 private:
87 ~ActiveVerifier();
grt (UTC plus 2) 2015/04/01 15:33:04 if the methods above truly need to be virtual, mak
rvargas (doing something else) 2015/04/01 16:51:03 There's no destructor implementation.
grt (UTC plus 2) 2015/04/01 20:33:02 Ah, so there isn't. Ack.
88
89 bool enabled_;
90 bool closing_;
91 NativeLock* lock_;
92 HandleMap map_;
93 DISALLOW_COPY_AND_ASSIGN(ActiveVerifier);
94 };
95 ActiveVerifier* g_active_verifier = NULL;
96
97 // static
98 void ActiveVerifier::InstallVerifier() {
99 #if defined(COMPONENT_BUILD)
100 AutoNativeLock lock(g_lock.Get());
101 g_active_verifier = new ActiveVerifier(true);
102 #else
103 HMODULE main_module = ::GetModuleHandle(NULL);
104 GetHandleVerifierFn get_handle_verifier =
105 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
106 main_module, "GetHandleVerifier"));
107
108 if (!get_handle_verifier) {
109 g_active_verifier = new ActiveVerifier(false);
grt (UTC plus 2) 2015/04/01 15:33:04 indentation
rvargas (doing something else) 2015/04/01 16:51:03 ... I saw that while testing and I forgot to fix i
110 return;
111 }
112
113 ActiveVerifier* verifier =
114 reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
115
116 AutoNativeLock lock(g_lock.Get());
117 g_active_verifier = verifier ? verifier : new ActiveVerifier(true);
118 #endif
119 }
120
121 bool ActiveVerifier::CloseHandle(HANDLE handle) {
122 if (!enabled_)
123 return CloseHandleWrapper(handle);
124
125 AutoNativeLock lock(*lock_);
126 closing_ = true;
127 CloseHandleWrapper(handle);
128 closing_ = false;
129
130 return true;
131 }
132
133 void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
134 const void* pc1, const void* pc2) {
135 if (!enabled_)
136 return;
137
138 // Grab the thread id before the lock.
139 DWORD thread_id = GetCurrentThreadId();
140
141 AutoNativeLock lock(*lock_);
142
143 Info handle_info = { owner, pc1, pc2, thread_id };
144 std::pair<HANDLE, Info> item(handle, handle_info);
145 std::pair<HandleMap::iterator, bool> result = map_.insert(item);
146 if (!result.second) {
147 Info other = result.first->second;
148 base::debug::Alias(&other);
149 CHECK(false);
150 }
151 }
152
153 void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
154 const void* pc1, const void* pc2) {
155 if (!enabled_)
156 return;
157
158 AutoNativeLock lock(*lock_);
159 HandleMap::iterator i = map_.find(handle);
160 if (i == map_.end())
161 CHECK(false);
162
163 Info other = i->second;
164 if (other.owner != owner) {
165 base::debug::Alias(&other);
166 CHECK(false);
167 }
168
169 map_.erase(i);
170 }
171
172 void ActiveVerifier::Disable() {
173 enabled_ = false;
174 }
175
176 void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
177 AutoNativeLock lock(*lock_);
178 if (closing_)
179 return;
180
181 HandleMap::iterator i = map_.find(handle);
182 if (i == map_.end())
183 return;
184
185 Info other = i->second;
186 base::debug::Alias(&other);
187 CHECK(false);
188 }
189
71 } // namespace 190 } // namespace
72 191
192 void* GetHandleVerifier() {
193 return g_active_verifier;
194 }
195
73 namespace base { 196 namespace base {
74 namespace win { 197 namespace win {
75 198
76 // Static. 199 // Static.
77 bool HandleTraits::CloseHandle(HANDLE handle) { 200 bool HandleTraits::CloseHandle(HANDLE handle) {
78 if (!g_verifier_enabled) 201 if (!g_active_verifier)
79 return CloseHandleWrapper(handle); 202 ActiveVerifier::InstallVerifier();
80 203
81 AutoNativeLock lock(g_lock.Get()); 204 return g_active_verifier->CloseHandle(handle);
82 g_closing = true;
83 CloseHandleWrapper(handle);
84 g_closing = false;
85
86 return true;
87 } 205 }
88 206
89 // Static. 207 // Static.
90 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, 208 void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
91 const void* pc1, const void* pc2) { 209 const void* pc1, const void* pc2) {
92 if (!g_verifier_enabled) 210 if (!g_active_verifier)
93 return; 211 ActiveVerifier::InstallVerifier();
94 212
95 // Grab the thread id before the lock. 213 return g_active_verifier->StartTracking(handle, owner, pc1, pc2);
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 } 214 }
109 215
110 // Static. 216 // Static.
111 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, 217 void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
112 const void* pc1, const void* pc2) { 218 const void* pc1, const void* pc2) {
113 if (!g_verifier_enabled) 219 if (!g_active_verifier)
114 return; 220 ActiveVerifier::InstallVerifier();
115 221
116 AutoNativeLock lock(g_lock.Get()); 222 return g_active_verifier->StopTracking(handle, owner, pc1, pc2);
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 } 223 }
129 224
130 void DisableHandleVerifier() { 225 void DisableHandleVerifier() {
131 g_verifier_enabled = false; 226 if (!g_active_verifier)
227 ActiveVerifier::InstallVerifier();
228
229 return g_active_verifier->Disable();
132 } 230 }
133 231
134 void OnHandleBeingClosed(HANDLE handle) { 232 void OnHandleBeingClosed(HANDLE handle) {
135 AutoNativeLock lock(g_lock.Get()); 233 if (!g_active_verifier)
136 if (g_closing) 234 ActiveVerifier::InstallVerifier();
137 return;
138 235
139 HandleMap::iterator i = g_handle_map.Get().find(handle); 236 return g_active_verifier->OnHandleBeingClosed(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 } 237 }
147 238
148 } // namespace win 239 } // namespace win
149 } // namespace base 240 } // 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