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

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: no functionality changes 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 void ThreadSafeAssignOrCreateActiveVerifier(ActiveVerifier* existing_verifier,
118 bool enabled = true) {
scottmg 2016/03/10 22:11:22 Is this allowed now? I think just passing true in
Will Harris 2016/03/10 22:14:23 it's not disallowed, and I see other examples in b
scottmg 2016/03/10 22:17:16 OK, I still don't think there's any utility when 3
Will Harris 2016/03/10 22:18:57 it tickled my OCD passing an ignored value for the
119 AutoNativeLock lock(g_lock.Get());
120 // Another thread in this module might be trying to assign the global
121 // verifier, so check that within the lock here.
122 if (g_active_verifier)
123 return;
124 g_active_verifier =
125 existing_verifier ? existing_verifier : new ActiveVerifier(enabled);
126 }
127
116 // static 128 // static
117 void ActiveVerifier::InstallVerifier() { 129 void ActiveVerifier::InstallVerifier() {
118 #if defined(COMPONENT_BUILD) 130 #if defined(COMPONENT_BUILD)
119 AutoNativeLock lock(g_lock.Get()); 131 // Component build has one Active Verifier per module.
120 g_active_verifier = new ActiveVerifier(true); 132 ThreadSafeAssignOrCreateActiveVerifier(nullptr, true);
121 #else 133 #else
122 // If you are reading this, wondering why your process seems deadlocked, take 134 // 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 135 // 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 136 // there, like doing whatever gave you that nice windows handle you are trying
125 // to store in a ScopedHandle. 137 // to store in a ScopedHandle.
126 HMODULE main_module = ::GetModuleHandle(NULL); 138 HMODULE main_module = ::GetModuleHandle(NULL);
127 GetHandleVerifierFn get_handle_verifier = 139 GetHandleVerifierFn get_handle_verifier =
128 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress( 140 reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress(
129 main_module, "GetHandleVerifier")); 141 main_module, "GetHandleVerifier"));
130 142
143 // This should only happen if running in a DLL is linked with base but the
144 // hosting EXE is not. In this case, create an ActiveVerifier for the current
145 // module but leave it disabled.
131 if (!get_handle_verifier) { 146 if (!get_handle_verifier) {
132 g_active_verifier = new ActiveVerifier(false); 147 ThreadSafeAssignOrCreateActiveVerifier(nullptr, false);
133 return; 148 return;
134 } 149 }
135 150
136 ActiveVerifier* verifier = 151 // Check if in the main module.
152 if (get_handle_verifier == GetHandleVerifier) {
153 ThreadSafeAssignOrCreateActiveVerifier(nullptr, true);
154 return;
155 }
156
157 ActiveVerifier* main_module_verifier =
137 reinterpret_cast<ActiveVerifier*>(get_handle_verifier()); 158 reinterpret_cast<ActiveVerifier*>(get_handle_verifier());
138 159
139 // This lock only protects against races in this module, which is fine. 160 // Main module should always on-demand create a verifier.
140 AutoNativeLock lock(g_lock.Get()); 161 DCHECK(main_module_verifier);
141 g_active_verifier = verifier ? verifier : new ActiveVerifier(true); 162
163 ThreadSafeAssignOrCreateActiveVerifier(main_module_verifier);
142 #endif 164 #endif
143 } 165 }
144 166
145 bool ActiveVerifier::CloseHandle(HANDLE handle) { 167 bool ActiveVerifier::CloseHandle(HANDLE handle) {
146 if (!enabled_) 168 if (!enabled_)
147 return CloseHandleWrapper(handle); 169 return CloseHandleWrapper(handle);
148 170
149 closing_.Set(true); 171 closing_.Set(true);
150 CloseHandleWrapper(handle); 172 CloseHandleWrapper(handle);
151 closing_.Set(false); 173 closing_.Set(false);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 236
215 Info other = i->second; 237 Info other = i->second;
216 base::debug::Alias(&other); 238 base::debug::Alias(&other);
217 base::debug::Alias(&creation_stack_); 239 base::debug::Alias(&creation_stack_);
218 CHECK(false); // CloseHandle called on tracked handle. 240 CHECK(false); // CloseHandle called on tracked handle.
219 } 241 }
220 242
221 } // namespace 243 } // namespace
222 244
223 void* GetHandleVerifier() { 245 void* GetHandleVerifier() {
224 return g_active_verifier; 246 return ActiveVerifier::Get();
225 } 247 }
226 248
227 namespace base { 249 namespace base {
228 namespace win { 250 namespace win {
229 251
230 // Static. 252 // Static.
231 bool HandleTraits::CloseHandle(HANDLE handle) { 253 bool HandleTraits::CloseHandle(HANDLE handle) {
232 return ActiveVerifier::Get()->CloseHandle(handle); 254 return ActiveVerifier::Get()->CloseHandle(handle);
233 } 255 }
234 256
(...skipping 12 matching lines...) Expand all
247 void DisableHandleVerifier() { 269 void DisableHandleVerifier() {
248 return ActiveVerifier::Get()->Disable(); 270 return ActiveVerifier::Get()->Disable();
249 } 271 }
250 272
251 void OnHandleBeingClosed(HANDLE handle) { 273 void OnHandleBeingClosed(HANDLE handle) {
252 return ActiveVerifier::Get()->OnHandleBeingClosed(handle); 274 return ActiveVerifier::Get()->OnHandleBeingClosed(handle);
253 } 275 }
254 276
255 } // namespace win 277 } // namespace win
256 } // namespace base 278 } // 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