tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CrossProcessMutex_posix.cpp (3081B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "CrossProcessMutex.h"
      8 #include "mozilla/ipc/SharedMemoryHandle.h"
      9 #include "nsDebug.h"
     10 #include "nsISupportsImpl.h"
     11 
     12 namespace {
     13 
     14 struct MutexData {
     15  pthread_mutex_t mMutex;
     16  mozilla::Atomic<int32_t> mCount;
     17 };
     18 
     19 }  // namespace
     20 
     21 namespace mozilla {
     22 
     23 static void InitMutex(pthread_mutex_t* mMutex) {
     24  pthread_mutexattr_t mutexAttributes;
     25  pthread_mutexattr_init(&mutexAttributes);
     26  // Make the mutex reentrant so it behaves the same as a win32 mutex
     27  if (pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE)) {
     28    MOZ_CRASH();
     29  }
     30  if (pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED)) {
     31    MOZ_CRASH();
     32  }
     33 
     34  if (pthread_mutex_init(mMutex, &mutexAttributes)) {
     35    MOZ_CRASH();
     36  }
     37 }
     38 
     39 CrossProcessMutex::CrossProcessMutex(const char*)
     40    : mMutex(nullptr), mCount(nullptr) {
     41 #if defined(MOZ_SANDBOX)
     42  // POSIX mutexes in shared memory aren't guaranteed to be safe - and
     43  // they specifically are not on Linux.
     44  MOZ_RELEASE_ASSERT(false);
     45 #endif
     46  mSharedBuffer = ipc::shared_memory::Create(sizeof(MutexData)).MapWithHandle();
     47  if (!mSharedBuffer) {
     48    MOZ_CRASH();
     49  }
     50 
     51  MutexData* data = mSharedBuffer.DataAs<MutexData>();
     52 
     53  if (!data) {
     54    MOZ_CRASH();
     55  }
     56 
     57  mMutex = &(data->mMutex);
     58  mCount = &(data->mCount);
     59 
     60  *mCount = 1;
     61  InitMutex(mMutex);
     62 
     63  MOZ_COUNT_CTOR(CrossProcessMutex);
     64 }
     65 
     66 CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
     67    : mMutex(nullptr), mCount(nullptr) {
     68  mSharedBuffer = std::move(aHandle).MapWithHandle();
     69  if (!mSharedBuffer) {
     70    MOZ_CRASH();
     71  }
     72 
     73  MutexData* data = mSharedBuffer.DataAs<MutexData>();
     74 
     75  if (!data) {
     76    MOZ_CRASH();
     77  }
     78 
     79  mMutex = &(data->mMutex);
     80  mCount = &(data->mCount);
     81  int32_t count = (*mCount)++;
     82 
     83  if (count == 0) {
     84    // The other side has already let go of their CrossProcessMutex, so now
     85    // mMutex is garbage. We need to re-initialize it.
     86    InitMutex(mMutex);
     87  }
     88 
     89  MOZ_COUNT_CTOR(CrossProcessMutex);
     90 }
     91 
     92 CrossProcessMutex::~CrossProcessMutex() {
     93  int32_t count = --(*mCount);
     94 
     95  if (count == 0) {
     96    // Nothing can be done if the destroy fails so ignore return code.
     97    (void)pthread_mutex_destroy(mMutex);
     98  }
     99 
    100  MOZ_COUNT_DTOR(CrossProcessMutex);
    101 }
    102 
    103 void CrossProcessMutex::Lock() {
    104  MOZ_ASSERT(*mCount > 0, "Attempting to lock mutex with zero ref count");
    105  pthread_mutex_lock(mMutex);
    106 }
    107 
    108 void CrossProcessMutex::Unlock() {
    109  MOZ_ASSERT(*mCount > 0, "Attempting to unlock mutex with zero ref count");
    110  pthread_mutex_unlock(mMutex);
    111 }
    112 
    113 CrossProcessMutexHandle CrossProcessMutex::CloneHandle() {
    114  if (mSharedBuffer) {
    115    auto handle = mSharedBuffer.Handle().Clone();
    116    if (!handle) {
    117      MOZ_CRASH();
    118    }
    119    return handle;
    120  }
    121  return nullptr;
    122 }
    123 
    124 }  // namespace mozilla