File: WindowsMutex.cpp

package info (click to toggle)
firefox-esr 128.13.0esr-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,230,012 kB
  • sloc: cpp: 7,103,971; javascript: 6,088,450; ansic: 3,653,980; python: 1,212,330; xml: 594,604; asm: 420,652; java: 182,969; sh: 71,124; makefile: 20,747; perl: 13,449; objc: 12,399; yacc: 4,583; cs: 3,846; pascal: 2,973; lex: 1,720; ruby: 1,194; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10
file content (103 lines) | stat: -rw-r--r-- 3,310 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/Logging.h"

#include "WindowsMutex.h"

namespace mozilla::default_agent {

using mozilla::LogLevel;

static LazyLogModule gWindowsMutexLog("WindowsMutex");

NS_IMPL_ISUPPORTS(WindowsMutexFactory, nsIWindowsMutexFactory)

NS_IMETHODIMP
WindowsMutexFactory::CreateMutex(const nsAString& aName,
                                 nsIWindowsMutex** aWindowsMutex) {
  nsAutoHandle mutex;
  auto name = PromiseFlatString(aName);

  mutex.own(CreateMutexW(nullptr, FALSE, name.get()));
  if (mutex.get() == nullptr) {
    MOZ_LOG(gWindowsMutexLog, LogLevel::Error,
            ("Couldn't open mutex \"%s\": %#lX",
             NS_ConvertUTF16toUTF8(name).get(), GetLastError()));
    return NS_ERROR_NOT_AVAILABLE;
  }

  RefPtr<WindowsMutex> nsMutex = new WindowsMutex(name, mutex);
  nsMutex.forget(aWindowsMutex);
  return NS_OK;
}

WindowsMutex::WindowsMutex(const nsString& aName, nsAutoHandle& aMutex)
    : mName(NS_ConvertUTF16toUTF8(aName)), mLocked(false) {
  mMutex.steal(aMutex);
}

WindowsMutex::~WindowsMutex() {
  Unlock();
  // nsAutoHandle will take care of closing the mutex's handle.
}

NS_IMPL_ISUPPORTS(WindowsMutex, nsIWindowsMutex)

NS_IMETHODIMP
WindowsMutex::TryLock() {
  // This object may be used on the main thread, so don't wait if it's
  // not signaled.
  DWORD mutexStatus = WaitForSingleObject(mMutex.get(), 0);
  if (mutexStatus == WAIT_OBJECT_0) {
    mLocked = true;
  } else if (mutexStatus == WAIT_TIMEOUT) {
    MOZ_LOG(gWindowsMutexLog, LogLevel::Warning,
            ("Timed out waiting for mutex \"%s\"", mName.get()));
  } else if (mutexStatus == WAIT_ABANDONED) {
    // This status code means that we are supposed to check our data for
    // consistency as the last locking process didn't signal intentional
    // unlocking which might indicate it crashed mid-operation. Current uses of
    // this `WindowsMutex` don't need to worry about corruption of the locked
    // object, if needed the `nsIWindowsMutex` interface should be extended.
    MOZ_LOG(gWindowsMutexLog, LogLevel::Warning,
            ("Found abandoned mutex \"%s\". Continuing...", mName.get()));
    mLocked = true;
  } else {
    // The only other documented status code is WAIT_FAILED. In the case that
    // we somehow get some other code, that is also an error.
    MOZ_LOG(gWindowsMutexLog, LogLevel::Error,
            ("Failed to wait on mutex: mName: %s, error %#lX", mName.get(),
             GetLastError()));
  }
  return mLocked ? NS_OK : NS_ERROR_NOT_AVAILABLE;
}

NS_IMETHODIMP
WindowsMutex::IsLocked(bool* aLocked) {
  *aLocked = mLocked;
  return NS_OK;
}

NS_IMETHODIMP
WindowsMutex::Unlock() {
  nsresult rv = NS_OK;

  if (mLocked) {
    BOOL success = ReleaseMutex(mMutex.get());
    if (!success) {
      MOZ_LOG(gWindowsMutexLog, LogLevel::Error,
              ("Failed to release mutex \"%s\"", mName.get()));
      rv = NS_ERROR_UNEXPECTED;
    }

    mLocked = false;
  }

  return rv;
}

}  // namespace mozilla::default_agent