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

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

Issue 1772343007: Two HandleVerifier thread safety fixes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nit Created 4 years, 9 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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <unordered_map> 9 #include <unordered_map>
10 10
(...skipping 23 matching lines...) Expand all
34 34
35 struct Info { 35 struct Info {
36 const void* owner; 36 const void* owner;
37 const void* pc1; 37 const void* pc1;
38 const void* pc2; 38 const void* pc2;
39 base::debug::StackTrace stack; 39 base::debug::StackTrace stack;
40 DWORD thread_id; 40 DWORD thread_id;
41 }; 41 };
42 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; 42 typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap;
43 43
44 // g_lock protects the handle map and setting g_active_verifier. 44 // g_lock protects the handle map and setting g_active_verifier within this
45 // module.
45 typedef base::internal::LockImpl NativeLock; 46 typedef base::internal::LockImpl NativeLock;
46 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; 47 base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
47 48
48 bool CloseHandleWrapper(HANDLE handle) {
49 if (!::CloseHandle(handle))
50 CHECK(false); // CloseHandle failed.
51 return true;
52 }
53
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();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 ActiveVerifier* g_active_verifier = NULL; 101 ActiveVerifier* g_active_verifier = NULL;
107 102
108 // static 103 // static
109 ActiveVerifier* ActiveVerifier::Get() { 104 ActiveVerifier* ActiveVerifier::Get() {
110 if (!g_active_verifier) 105 if (!g_active_verifier)
111 ActiveVerifier::InstallVerifier(); 106 ActiveVerifier::InstallVerifier();
112 107
113 return g_active_verifier; 108 return g_active_verifier;
114 } 109 }
115 110
111 bool CloseHandleWrapper(HANDLE handle) {
112 if (!::CloseHandle(handle))
113 CHECK(false); // CloseHandle failed.
114 return true;
115 }
116
117 // Assigns the g_active_verifier global within the g_lock lock.
118 // If |existing_verifier| is non-null then |enabled| is ignored.
119 void ThreadSafeAssignOrCreateActiveVerifier(ActiveVerifier* existing_verifier,
120 bool enabled) {
121 AutoNativeLock lock(g_lock.Get());
122 // Another thread in this module might be trying to assign the global
123 // verifier, so check that within the lock here.
124 if (g_active_verifier)
125 return;
126 g_active_verifier =
127 existing_verifier ? existing_verifier : new ActiveVerifier(enabled);
128 }
129
116 // static 130 // static
117 void ActiveVerifier::InstallVerifier() { 131 void ActiveVerifier::InstallVerifier() {
118 #if defined(COMPONENT_BUILD) 132 #if defined(COMPONENT_BUILD)
119 AutoNativeLock lock(g_lock.Get()); 133 // Component build has one Active Verifier per module.
120 g_active_verifier = new ActiveVerifier(true); 134 ThreadSafeAssignOrCreateActiveVerifier(nullptr, true);
121 #else 135 #else
122 // If you are reading this, wondering why your process seems deadlocked, take 136 // If you are reading this, wondering why your process seems deadlocked, take
123 // a look at your DllMain code and remove things that should not be done 137 // a look at your DllMain code and remove things that should not be done
124 // there, like doing whatever gave you that nice windows handle you are trying 138 // there, like doing whatever gave you that nice windows handle you are trying
125 // to store in a ScopedHandle. 139 // to store in a ScopedHandle.
126 HMODULE main_module = ::GetModuleHandle(NULL); 140 HMODULE main_module = ::GetModuleHandle(NULL);
127 GetHandleVerifierFn get_handle_verifier = 141 GetHandleVerifierFn get_handle_verifier =
128 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress( 142 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
129 main_module, "GetHandleVerifier")); 143 main_module, "GetHandleVerifier"));
130 144
145 // This should only happen if running in a DLL is linked with base but the
146 // hosting EXE is not. In this case, create an ActiveVerifier for the current
147 // module but leave it disabled.
131 if (!get_handle_verifier) { 148 if (!get_handle_verifier) {
132 g_active_verifier = new ActiveVerifier(false); 149 ThreadSafeAssignOrCreateActiveVerifier(nullptr, false);
133 return; 150 return;
134 } 151 }
135 152
136 ActiveVerifier* verifier = 153 // Check if in the main module.
154 if (get_handle_verifier == GetHandleVerifier) {
155 ThreadSafeAssignOrCreateActiveVerifier(nullptr, true);
156 return;
157 }
158
159 ActiveVerifier* main_module_verifier =
137 reinterpret_cast<ActiveVerifier*>(get_handle_verifier()); 160 reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
138 161
139 // This lock only protects against races in this module, which is fine. 162 // Main module should always on-demand create a verifier.
140 AutoNativeLock lock(g_lock.Get()); 163 DCHECK(main_module_verifier);
141 g_active_verifier = verifier ? verifier : new ActiveVerifier(true); 164
165 ThreadSafeAssignOrCreateActiveVerifier(main_module_verifier, false);
142 #endif 166 #endif
143 } 167 }
144 168
145 bool ActiveVerifier::CloseHandle(HANDLE handle) { 169 bool ActiveVerifier::CloseHandle(HANDLE handle) {
146 if (!enabled_) 170 if (!enabled_)
147 return CloseHandleWrapper(handle); 171 return CloseHandleWrapper(handle);
148 172
149 closing_.Set(true); 173 closing_.Set(true);
150 CloseHandleWrapper(handle); 174 CloseHandleWrapper(handle);
151 closing_.Set(false); 175 closing_.Set(false);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 238
215 Info other = i->second; 239 Info other = i->second;
216 base::debug::Alias(&other); 240 base::debug::Alias(&other);
217 base::debug::Alias(&creation_stack_); 241 base::debug::Alias(&creation_stack_);
218 CHECK(false); // CloseHandle called on tracked handle. 242 CHECK(false); // CloseHandle called on tracked handle.
219 } 243 }
220 244
221 } // namespace 245 } // namespace
222 246
223 void* GetHandleVerifier() { 247 void* GetHandleVerifier() {
224 return g_active_verifier; 248 return ActiveVerifier::Get();
225 } 249 }
226 250
227 namespace base { 251 namespace base {
228 namespace win { 252 namespace win {
229 253
230 // Static. 254 // Static.
231 bool HandleTraits::CloseHandle(HANDLE handle) { 255 bool HandleTraits::CloseHandle(HANDLE handle) {
232 return ActiveVerifier::Get()->CloseHandle(handle); 256 return ActiveVerifier::Get()->CloseHandle(handle);
233 } 257 }
234 258
(...skipping 12 matching lines...) Expand all
247 void DisableHandleVerifier() { 271 void DisableHandleVerifier() {
248 return ActiveVerifier::Get()->Disable(); 272 return ActiveVerifier::Get()->Disable();
249 } 273 }
250 274
251 void OnHandleBeingClosed(HANDLE handle) { 275 void OnHandleBeingClosed(HANDLE handle) {
252 return ActiveVerifier::Get()->OnHandleBeingClosed(handle); 276 return ActiveVerifier::Get()->OnHandleBeingClosed(handle);
253 } 277 }
254 278
255 } // namespace win 279 } // namespace win
256 } // namespace base 280 } // 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