• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef BASE_THREADING_THREAD_RESTRICTIONS_H_
6 #define BASE_THREADING_THREAD_RESTRICTIONS_H_
7 
8 #include "base/base_export.h"
9 #include "base/gtest_prod_util.h"
10 #include "base/logging.h"
11 #include "base/macros.h"
12 
13 class BrowserProcessImpl;
14 class HistogramSynchronizer;
15 class NativeBackendKWallet;
16 class KeyStorageLinux;
17 
18 namespace android_webview {
19 class AwFormDatabaseService;
20 class CookieManager;
21 class ScopedAllowInitGLBindings;
22 }
23 
24 namespace cc {
25 class CompletionEvent;
26 class SingleThreadTaskGraphRunner;
27 }
28 namespace chromeos {
29 class BlockingMethodCaller;
30 namespace system {
31 class StatisticsProviderImpl;
32 }
33 }
34 namespace chrome_browser_net {
35 class Predictor;
36 }
37 namespace content {
38 class BrowserGpuChannelHostFactory;
39 class BrowserGpuMemoryBufferManager;
40 class BrowserMainLoop;
41 class BrowserProcessSubThread;
42 class BrowserShutdownProfileDumper;
43 class BrowserTestBase;
44 class CategorizedWorkerPool;
45 class GpuProcessTransportFactory;
46 class NestedMessagePumpAndroid;
47 class ScopedAllowWaitForAndroidLayoutTests;
48 class ScopedAllowWaitForDebugURL;
49 class SessionStorageDatabase;
50 class SoftwareOutputDeviceMus;
51 class ServiceWorkerSubresourceLoader;
52 class SynchronousCompositor;
53 class SynchronousCompositorHost;
54 class SynchronousCompositorSyncCallBridge;
55 class TextInputClientMac;
56 }  // namespace content
57 namespace cronet {
58 class CronetPrefsManager;
59 class CronetURLRequestContext;
60 }  // namespace cronet
61 namespace dbus {
62 class Bus;
63 }
64 namespace disk_cache {
65 class BackendImpl;
66 class InFlightIO;
67 }
68 namespace functions {
69 class ExecScriptScopedAllowBaseSyncPrimitives;
70 }
71 namespace gpu {
72 class GpuChannelHost;
73 }
74 namespace leveldb {
75 class LevelDBMojoProxy;
76 }
77 namespace media {
78 class AudioInputDevice;
79 class BlockingUrlProtocol;
80 }
81 namespace midi {
82 class TaskService;  // https://crbug.com/796830
83 }
84 namespace mojo {
85 class CoreLibraryInitializer;
86 class SyncCallRestrictions;
87 namespace core {
88 class ScopedIPCSupport;
89 }
90 }
91 namespace rlz_lib {
92 class FinancialPing;
93 }
94 namespace ui {
95 class CommandBufferClientImpl;
96 class CommandBufferLocal;
97 class GpuState;
98 class MaterialDesignController;
99 }
100 namespace net {
101 class MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
102 class NetworkChangeNotifierMac;
103 namespace internal {
104 class AddressTrackerLinux;
105 }
106 }
107 
108 namespace remoting {
109 class AutoThread;
110 }
111 
112 namespace resource_coordinator {
113 class TabManagerDelegate;
114 }
115 
116 namespace service_manager {
117 class ServiceProcessLauncher;
118 }
119 
120 namespace shell_integration {
121 class LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
122 }
123 
124 namespace ui {
125 class WindowResizeHelperMac;
126 }
127 
128 namespace views {
129 class ScreenMus;
130 }
131 
132 namespace viz {
133 class HostGpuMemoryBufferManager;
134 }
135 
136 namespace webrtc {
137 class DesktopConfigurationMonitor;
138 }
139 
140 namespace base {
141 
142 namespace android {
143 class JavaHandlerThread;
144 }
145 
146 namespace internal {
147 class TaskTracker;
148 }
149 
150 class GetAppOutputScopedAllowBaseSyncPrimitives;
151 class SimpleThread;
152 class StackSamplingProfiler;
153 class Thread;
154 class ThreadTestHelper;
155 
156 #if DCHECK_IS_ON()
157 #define INLINE_IF_DCHECK_IS_OFF BASE_EXPORT
158 #define EMPTY_BODY_IF_DCHECK_IS_OFF
159 #else
160 #define INLINE_IF_DCHECK_IS_OFF inline
161 #define EMPTY_BODY_IF_DCHECK_IS_OFF \
162   {}
163 #endif
164 
165 // A "blocking call" refers to any call that causes the calling thread to wait
166 // off-CPU. It includes but is not limited to calls that wait on synchronous
167 // file I/O operations: read or write a file from disk, interact with a pipe or
168 // a socket, rename or delete a file, enumerate files in a directory, etc.
169 // Acquiring a low contention lock is not considered a blocking call.
170 
171 // Asserts that blocking calls are allowed in the current scope.
172 //
173 // Style tip: It's best if you put AssertBlockingAllowed() checks as close to
174 // the blocking call as possible. For example:
175 //
176 // void ReadFile() {
177 //   PreWork();
178 //
179 //   base::AssertBlockingAllowed();
180 //   fopen(...);
181 //
182 //   PostWork();
183 // }
184 //
185 // void Bar() {
186 //   ReadFile();
187 // }
188 //
189 // void Foo() {
190 //   Bar();
191 // }
192 INLINE_IF_DCHECK_IS_OFF void AssertBlockingAllowed()
193     EMPTY_BODY_IF_DCHECK_IS_OFF;
194 
195 // Disallows blocking on the current thread.
196 INLINE_IF_DCHECK_IS_OFF void DisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
197 
198 // Disallows blocking calls within its scope.
199 class BASE_EXPORT ScopedDisallowBlocking {
200  public:
201   ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
202   ~ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
203 
204  private:
205 #if DCHECK_IS_ON()
206   const bool was_disallowed_;
207 #endif
208 
209   DISALLOW_COPY_AND_ASSIGN(ScopedDisallowBlocking);
210 };
211 
212 // ScopedAllowBlocking(ForTesting) allow blocking calls within a scope where
213 // they are normally disallowed.
214 //
215 // Avoid using this. Prefer making blocking calls from tasks posted to
216 // base::TaskScheduler with base::MayBlock().
217 //
218 // Where unavoidable, put ScopedAllow* instances in the narrowest scope possible
219 // in the caller making the blocking call but no further down. That is: if a
220 // Cleanup() method needs to do a blocking call, document Cleanup() as blocking
221 // and add a ScopedAllowBlocking instance in callers that can't avoid making
222 // this call from a context where blocking is banned, as such:
223 //   void Client::MyMethod() {
224 //     (...)
225 //     {
226 //       // Blocking is okay here because XYZ.
227 //       ScopedAllowBlocking allow_blocking;
228 //       my_foo_->Cleanup();
229 //     }
230 //     (...)
231 //   }
232 //
233 //   // This method can block.
234 //   void Foo::Cleanup() {
235 //     // Do NOT add the ScopedAllowBlocking in Cleanup() directly as that hides
236 //     // its blocking nature from unknowing callers and defeats the purpose of
237 //     // these checks.
238 //     FlushStateToDisk();
239 //   }
240 //
241 // Note: In rare situations where the blocking call is an implementation detail
242 // (i.e. the impl makes a call that invokes AssertBlockingAllowed() but it
243 // somehow knows that in practice this will not block), it might be okay to hide
244 // the ScopedAllowBlocking instance in the impl with a comment explaining why
245 // that's okay.
246 class BASE_EXPORT ScopedAllowBlocking {
247  private:
248   // This can only be instantiated by friends. Use ScopedAllowBlockingForTesting
249   // in unit tests to avoid the friend requirement.
250   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest, ScopedAllowBlocking);
251   friend class android_webview::ScopedAllowInitGLBindings;
252   friend class content::BrowserProcessSubThread;
253   friend class content::GpuProcessTransportFactory;
254   friend class cronet::CronetPrefsManager;
255   friend class cronet::CronetURLRequestContext;
256   friend class media::AudioInputDevice;
257   friend class mojo::CoreLibraryInitializer;
258   friend class resource_coordinator::TabManagerDelegate;  // crbug.com/778703
259   friend class ui::MaterialDesignController;
260   friend class ScopedAllowBlockingForTesting;
261   friend class StackSamplingProfiler;
262 
263   ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
264   ~ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
265 
266 #if DCHECK_IS_ON()
267   const bool was_disallowed_;
268 #endif
269 
270   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlocking);
271 };
272 
273 class ScopedAllowBlockingForTesting {
274  public:
ScopedAllowBlockingForTesting()275   ScopedAllowBlockingForTesting() {}
~ScopedAllowBlockingForTesting()276   ~ScopedAllowBlockingForTesting() {}
277 
278  private:
279 #if DCHECK_IS_ON()
280   ScopedAllowBlocking scoped_allow_blocking_;
281 #endif
282 
283   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlockingForTesting);
284 };
285 
286 // "Waiting on a //base sync primitive" refers to calling one of these methods:
287 // - base::WaitableEvent::*Wait*
288 // - base::ConditionVariable::*Wait*
289 // - base::Process::WaitForExit*
290 
291 // Disallows waiting on a //base sync primitive on the current thread.
292 INLINE_IF_DCHECK_IS_OFF void DisallowBaseSyncPrimitives()
293     EMPTY_BODY_IF_DCHECK_IS_OFF;
294 
295 // ScopedAllowBaseSyncPrimitives(ForTesting)(OutsideBlockingScope) allow waiting
296 // on a //base sync primitive within a scope where this is normally disallowed.
297 //
298 // Avoid using this.
299 //
300 // Instead of waiting on a WaitableEvent or a ConditionVariable, put the work
301 // that should happen after the wait in a callback and post that callback from
302 // where the WaitableEvent or ConditionVariable would have been signaled. If
303 // something needs to be scheduled after many tasks have executed, use
304 // base::BarrierClosure.
305 //
306 // On Windows, join processes asynchronously using base::win::ObjectWatcher.
307 
308 // This can only be used in a scope where blocking is allowed.
309 class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
310  private:
311   // This can only be instantiated by friends. Use
312   // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
313   // requirement.
314   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
315                            ScopedAllowBaseSyncPrimitives);
316   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
317                            ScopedAllowBaseSyncPrimitivesResetsState);
318   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
319                            ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed);
320   friend class base::GetAppOutputScopedAllowBaseSyncPrimitives;
321   friend class content::BrowserProcessSubThread;
322   friend class content::SessionStorageDatabase;
323   friend class functions::ExecScriptScopedAllowBaseSyncPrimitives;
324   friend class leveldb::LevelDBMojoProxy;
325   friend class media::BlockingUrlProtocol;
326   friend class mojo::core::ScopedIPCSupport;
327   friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
328   friend class rlz_lib::FinancialPing;
329   friend class shell_integration::LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
330   friend class webrtc::DesktopConfigurationMonitor;
331   friend class content::ServiceWorkerSubresourceLoader;
332   friend class viz::HostGpuMemoryBufferManager;
333 
334   ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
335   ~ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
336 
337 #if DCHECK_IS_ON()
338   const bool was_disallowed_;
339 #endif
340 
341   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitives);
342 };
343 
344 // This can be used in a scope where blocking is disallowed.
345 class BASE_EXPORT ScopedAllowBaseSyncPrimitivesOutsideBlockingScope {
346  private:
347   // This can only be instantiated by friends. Use
348   // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
349   // requirement.
350   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
351                            ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
352   FRIEND_TEST_ALL_PREFIXES(
353       ThreadRestrictionsTest,
354       ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState);
355   friend class ::KeyStorageLinux;
356   friend class content::SynchronousCompositor;
357   friend class content::SynchronousCompositorHost;
358   friend class content::SynchronousCompositorSyncCallBridge;
359   friend class midi::TaskService;  // https://crbug.com/796830
360   // Not used in production yet, https://crbug.com/844078.
361   friend class service_manager::ServiceProcessLauncher;
362 
363   ScopedAllowBaseSyncPrimitivesOutsideBlockingScope()
364       EMPTY_BODY_IF_DCHECK_IS_OFF;
365   ~ScopedAllowBaseSyncPrimitivesOutsideBlockingScope()
366       EMPTY_BODY_IF_DCHECK_IS_OFF;
367 
368 #if DCHECK_IS_ON()
369   const bool was_disallowed_;
370 #endif
371 
372   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
373 };
374 
375 // This can be used in tests without being a friend of
376 // ScopedAllowBaseSyncPrimitives(OutsideBlockingScope).
377 class BASE_EXPORT ScopedAllowBaseSyncPrimitivesForTesting {
378  public:
379   ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
380   ~ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
381 
382  private:
383 #if DCHECK_IS_ON()
384   const bool was_disallowed_;
385 #endif
386 
387   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesForTesting);
388 };
389 
390 namespace internal {
391 
392 // Asserts that waiting on a //base sync primitive is allowed in the current
393 // scope.
394 INLINE_IF_DCHECK_IS_OFF void AssertBaseSyncPrimitivesAllowed()
395     EMPTY_BODY_IF_DCHECK_IS_OFF;
396 
397 // Resets all thread restrictions on the current thread.
398 INLINE_IF_DCHECK_IS_OFF void ResetThreadRestrictionsForTesting()
399     EMPTY_BODY_IF_DCHECK_IS_OFF;
400 
401 }  // namespace internal
402 
403 class BASE_EXPORT ThreadRestrictions {
404  public:
405   // Constructing a ScopedAllowIO temporarily allows IO for the current
406   // thread.  Doing this is almost certainly always incorrect.
407   //
408   // DEPRECATED. Use ScopedAllowBlocking(ForTesting).
409   class BASE_EXPORT ScopedAllowIO {
410    public:
411     ScopedAllowIO() EMPTY_BODY_IF_DCHECK_IS_OFF;
412     ~ScopedAllowIO() EMPTY_BODY_IF_DCHECK_IS_OFF;
413 
414    private:
415 #if DCHECK_IS_ON()
416     const bool was_allowed_;
417 #endif
418 
419     DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO);
420   };
421 
422 #if DCHECK_IS_ON()
423   // Set whether the current thread to make IO calls.
424   // Threads start out in the *allowed* state.
425   // Returns the previous value.
426   //
427   // DEPRECATED. Use ScopedAllowBlocking(ForTesting) or ScopedDisallowBlocking.
428   static bool SetIOAllowed(bool allowed);
429 
430   // Set whether the current thread can use singletons.  Returns the previous
431   // value.
432   static bool SetSingletonAllowed(bool allowed);
433 
434   // Check whether the current thread is allowed to use singletons (Singleton /
435   // LazyInstance).  DCHECKs if not.
436   static void AssertSingletonAllowed();
437 
438   // Disable waiting on the current thread. Threads start out in the *allowed*
439   // state. Returns the previous value.
440   //
441   // DEPRECATED. Use DisallowBaseSyncPrimitives.
442   static void DisallowWaiting();
443 #else
444   // Inline the empty definitions of these functions so that they can be
445   // compiled out.
SetIOAllowed(bool allowed)446   static bool SetIOAllowed(bool allowed) { return true; }
SetSingletonAllowed(bool allowed)447   static bool SetSingletonAllowed(bool allowed) { return true; }
AssertSingletonAllowed()448   static void AssertSingletonAllowed() {}
DisallowWaiting()449   static void DisallowWaiting() {}
450 #endif
451 
452  private:
453   // DO NOT ADD ANY OTHER FRIEND STATEMENTS.
454   // BEGIN ALLOWED USAGE.
455   friend class android_webview::AwFormDatabaseService;
456   friend class android_webview::CookieManager;
457   friend class base::StackSamplingProfiler;
458   friend class content::BrowserMainLoop;
459   friend class content::BrowserShutdownProfileDumper;
460   friend class content::BrowserTestBase;
461   friend class content::NestedMessagePumpAndroid;
462   friend class content::ScopedAllowWaitForAndroidLayoutTests;
463   friend class content::ScopedAllowWaitForDebugURL;
464   friend class ::HistogramSynchronizer;
465   friend class internal::TaskTracker;
466   friend class cc::CompletionEvent;
467   friend class cc::SingleThreadTaskGraphRunner;
468   friend class content::CategorizedWorkerPool;
469   friend class remoting::AutoThread;
470   friend class ui::WindowResizeHelperMac;
471   friend class MessagePumpDefault;
472   friend class SimpleThread;
473   friend class Thread;
474   friend class ThreadTestHelper;
475   friend class PlatformThread;
476   friend class android::JavaHandlerThread;
477   friend class mojo::SyncCallRestrictions;
478   friend class ui::CommandBufferClientImpl;
479   friend class ui::CommandBufferLocal;
480   friend class ui::GpuState;
481 
482   // END ALLOWED USAGE.
483   // BEGIN USAGE THAT NEEDS TO BE FIXED.
484   friend class ::chromeos::BlockingMethodCaller;  // http://crbug.com/125360
485   friend class ::chromeos::system::StatisticsProviderImpl;  // http://crbug.com/125385
486   friend class chrome_browser_net::Predictor;     // http://crbug.com/78451
487   friend class
488       content::BrowserGpuChannelHostFactory;      // http://crbug.com/125248
489   friend class
490       content::BrowserGpuMemoryBufferManager;     // http://crbug.com/420368
491   friend class content::TextInputClientMac;       // http://crbug.com/121917
492   friend class dbus::Bus;                         // http://crbug.com/125222
493   friend class disk_cache::BackendImpl;           // http://crbug.com/74623
494   friend class disk_cache::InFlightIO;            // http://crbug.com/74623
495   friend class gpu::GpuChannelHost;               // http://crbug.com/125264
496   friend class net::internal::AddressTrackerLinux;  // http://crbug.com/125097
497   friend class net::NetworkChangeNotifierMac;     // http://crbug.com/125097
498   friend class ::BrowserProcessImpl;              // http://crbug.com/125207
499   friend class ::NativeBackendKWallet;            // http://crbug.com/125331
500 #if !defined(OFFICIAL_BUILD)
501   friend class content::SoftwareOutputDeviceMus;  // Interim non-production code
502 #endif
503   friend class views::ScreenMus;
504 // END USAGE THAT NEEDS TO BE FIXED.
505 
506 #if DCHECK_IS_ON()
507   // DEPRECATED. Use ScopedAllowBaseSyncPrimitives.
508   static bool SetWaitAllowed(bool allowed);
509 #else
SetWaitAllowed(bool allowed)510   static bool SetWaitAllowed(bool allowed) { return true; }
511 #endif
512 
513   // Constructing a ScopedAllowWait temporarily allows waiting on the current
514   // thread.  Doing this is almost always incorrect, which is why we limit who
515   // can use this through friend.
516   //
517   // DEPRECATED. Use ScopedAllowBaseSyncPrimitives.
518   class BASE_EXPORT ScopedAllowWait {
519    public:
520     ScopedAllowWait() EMPTY_BODY_IF_DCHECK_IS_OFF;
521     ~ScopedAllowWait() EMPTY_BODY_IF_DCHECK_IS_OFF;
522 
523    private:
524 #if DCHECK_IS_ON()
525     const bool was_allowed_;
526 #endif
527 
528     DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait);
529   };
530 
531   DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions);
532 };
533 
534 }  // namespace base
535 
536 #endif  // BASE_THREADING_THREAD_RESTRICTIONS_H_
537