Home | History | Annotate | Download | only in lib
      1 // Copyright 2016 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 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
      6 
      7 #if ENABLE_SYNC_CALL_RESTRICTIONS
      8 
      9 #include "base/debug/leak_annotations.h"
     10 #include "base/logging.h"
     11 #include "base/macros.h"
     12 #include "base/no_destructor.h"
     13 #include "base/synchronization/lock.h"
     14 #include "base/threading/sequence_local_storage_slot.h"
     15 #include "mojo/public/c/system/core.h"
     16 
     17 namespace mojo {
     18 
     19 namespace {
     20 
     21 class GlobalSyncCallSettings {
     22  public:
     23   GlobalSyncCallSettings() = default;
     24   ~GlobalSyncCallSettings() = default;
     25 
     26   bool sync_call_allowed_by_default() const {
     27     base::AutoLock lock(lock_);
     28     return sync_call_allowed_by_default_;
     29   }
     30 
     31   void DisallowSyncCallByDefault() {
     32     base::AutoLock lock(lock_);
     33     sync_call_allowed_by_default_ = false;
     34   }
     35 
     36  private:
     37   mutable base::Lock lock_;
     38   bool sync_call_allowed_by_default_ = true;
     39 
     40   DISALLOW_COPY_AND_ASSIGN(GlobalSyncCallSettings);
     41 };
     42 
     43 GlobalSyncCallSettings& GetGlobalSettings() {
     44   static base::NoDestructor<GlobalSyncCallSettings> global_settings;
     45   return *global_settings;
     46 }
     47 
     48 size_t& GetSequenceLocalScopedAllowCount() {
     49   static base::NoDestructor<base::SequenceLocalStorageSlot<size_t>> count;
     50   return count->Get();
     51 }
     52 
     53 }  // namespace
     54 
     55 // static
     56 void SyncCallRestrictions::AssertSyncCallAllowed() {
     57   if (GetGlobalSettings().sync_call_allowed_by_default())
     58     return;
     59   if (GetSequenceLocalScopedAllowCount() > 0)
     60     return;
     61 
     62   LOG(FATAL) << "Mojo sync calls are not allowed in this process because "
     63              << "they can lead to jank and deadlock. If you must make an "
     64              << "exception, please see "
     65              << "SyncCallRestrictions::ScopedAllowSyncCall and consult "
     66              << "mojo/OWNERS.";
     67 }
     68 
     69 // static
     70 void SyncCallRestrictions::DisallowSyncCall() {
     71   GetGlobalSettings().DisallowSyncCallByDefault();
     72 }
     73 
     74 // static
     75 void SyncCallRestrictions::IncreaseScopedAllowCount() {
     76   ++GetSequenceLocalScopedAllowCount();
     77 }
     78 
     79 // static
     80 void SyncCallRestrictions::DecreaseScopedAllowCount() {
     81   DCHECK_GT(GetSequenceLocalScopedAllowCount(), 0u);
     82   --GetSequenceLocalScopedAllowCount();
     83 }
     84 
     85 }  // namespace mojo
     86 
     87 #endif  // ENABLE_SYNC_CALL_RESTRICTIONS
     88