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

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

Issue 1124763003: Update from https://crrev.com/327068 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: update nacl, buildtools, fix display_change_notifier_unittest Created 5 years, 7 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
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
136 // TODO(shrikant): Enable handle verifier after figuring out
137 // AppContainer/DuplicateHandle error.
138 g_active_verifier->Disable();
139 #endif
140 }
141
142 bool ActiveVerifier::CloseHandle(HANDLE handle) {
143 if (!enabled_)
144 return CloseHandleWrapper(handle);
145
146 AutoNativeLock lock(*lock_);
147 closing_ = true;
148 CloseHandleWrapper(handle);
149 closing_ = false;
150
151 return true;
152 }
153
154 void ActiveVerifier::StartTracking(HANDLE handle, const void* owner,
155 const void* pc1, const void* pc2) {
156 if (!enabled_)
157 return;
158
159 // Grab the thread id before the lock.
160 DWORD thread_id = GetCurrentThreadId();
161
162 AutoNativeLock lock(*lock_);
163
164 Info handle_info = { owner, pc1, pc2, thread_id };
165 std::pair<HANDLE, Info> item(handle, handle_info);
166 std::pair<HandleMap::iterator, bool> result = map_.insert(item);
167 if (!result.second) {
168 Info other = result.first->second;
169 base::debug::Alias(&other);
170 CHECK(false);
171 }
172 }
173
174 void ActiveVerifier::StopTracking(HANDLE handle, const void* owner,
175 const void* pc1, const void* pc2) {
176 if (!enabled_)
177 return;
178
179 AutoNativeLock lock(*lock_);
180 HandleMap::iterator i = map_.find(handle);
181 if (i == map_.end())
182 CHECK(false);
183
184 Info other = i->second;
185 if (other.owner != owner) {
186 base::debug::Alias(&other);
187 CHECK(false);
188 }
189
190 map_.erase(i);
191 }
192
193 void ActiveVerifier::Disable() {
194 enabled_ = false;
195 }
196
197 void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) {
198 AutoNativeLock lock(*lock_);
199 if (closing_)
200 return;
201
202 HandleMap::iterator i = map_.find(handle);
203 if (i == map_.end())
204 return;
205
206 Info other = i->second;
207 base::debug::Alias(&other);
208 CHECK(false);
209 }
210
71 } // namespace 211 } // namespace
72 212
213 void* GetHandleVerifier() {
214 return g_active_verifier;
215 }
216
73 namespace base { 217 namespace base {
74 namespace win { 218 namespace win {
75 219
76 // Static. 220 // Static.
77 bool HandleTraits::CloseHandle(HANDLE handle) { 221 bool HandleTraits::CloseHandle(HANDLE handle) {
78 if (!g_verifier_enabled) 222 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 } 223 }
88 224
89 // Static. 225 // Static.
90 void VerifierTraits::StartTracking(HANDLE handle, const void* owner, 226 void VerifierTraits::StartTracking(HANDLE handle, const void* owner,
91 const void* pc1, const void* pc2) { 227 const void* pc1, const void* pc2) {
92 if (!g_verifier_enabled) 228 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 } 229 }
109 230
110 // Static. 231 // Static.
111 void VerifierTraits::StopTracking(HANDLE handle, const void* owner, 232 void VerifierTraits::StopTracking(HANDLE handle, const void* owner,
112 const void* pc1, const void* pc2) { 233 const void* pc1, const void* pc2) {
113 if (!g_verifier_enabled) 234 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 } 235 }
129 236
130 void DisableHandleVerifier() { 237 void DisableHandleVerifier() {
131 g_verifier_enabled = false; 238 return ActiveVerifier::Get()->Disable();
132 } 239 }
133 240
134 void OnHandleBeingClosed(HANDLE handle) { 241 void OnHandleBeingClosed(HANDLE handle) {
135 AutoNativeLock lock(g_lock.Get()); 242 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 } 243 }
147 244
148 } // namespace win 245 } // namespace win
149 } // namespace base 246 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698