tor-browser

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

commit 6670c30e05cd77aa6aa716957793f0e5dcbaeab4
parent 5278a541b3b5cbf16190208389f2fb904d4914b3
Author: Markus Stange <mstange.moz@gmail.com>
Date:   Thu, 23 Oct 2025 20:44:35 +0000

Bug 1996126 - Make nsCocoaFeatures::macOSVersion() handle concurrent calls. r=jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D269881

Diffstat:
Mwidget/cocoa/nsCocoaFeatures.h | 4+---
Mwidget/cocoa/nsCocoaFeatures.mm | 30+++++++++++++++++++-----------
2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/widget/cocoa/nsCocoaFeatures.h b/widget/cocoa/nsCocoaFeatures.h @@ -42,9 +42,7 @@ class nsCocoaFeatures { private: nsCocoaFeatures() = delete; // Prevent instantiation. - static void InitializeVersionNumbers(); - - static int32_t mOSVersion; + static int32_t ComputeVersion(); }; #endif // nsCocoaFeatures_h_ diff --git a/widget/cocoa/nsCocoaFeatures.mm b/widget/cocoa/nsCocoaFeatures.mm @@ -34,10 +34,12 @@ #include "nsDebug.h" #include "nsObjCExceptions.h" +#include <atomic> #import <Cocoa/Cocoa.h> #include <sys/sysctl.h> -/*static*/ int32_t nsCocoaFeatures::mOSVersion = 0; +// The lazily-initialized version. 0 before initialization, non-zero after. +static std::atomic<int32_t> sOSVersion = 0; // This should not be called with unchecked aMajor, which should be >= 10. inline int32_t AssembleVersion(int32_t aMajor, int32_t aMinor, @@ -117,8 +119,8 @@ int32_t nsCocoaFeatures::GetVersion(int32_t aMajor, int32_t aMinor, return macOSVersion; } -/*static*/ void nsCocoaFeatures::InitializeVersionNumbers() { - NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; +/*static*/ int32_t nsCocoaFeatures::ComputeVersion() { + NS_OBJC_BEGIN_TRY_BLOCK_RETURN; // Provide an autorelease pool to avoid leaking Cocoa objects, // as this gets called before the main autorelease pool is in place. @@ -126,19 +128,25 @@ int32_t nsCocoaFeatures::GetVersion(int32_t aMajor, int32_t aMinor, int major, minor, bugfix; GetSystemVersion(major, minor, bugfix); - mOSVersion = GetVersion(major, minor, bugfix); + return GetVersion(major, minor, bugfix); - NS_OBJC_END_TRY_IGNORE_BLOCK; + NS_OBJC_END_TRY_BLOCK_RETURN(0); } /* static */ int32_t nsCocoaFeatures::macOSVersion() { - // Don't let this be called while we're first setting the value... - MOZ_ASSERT((mOSVersion & MACOS_VERSION_MASK) >= 0); - if (!mOSVersion) { - mOSVersion = -1; - InitializeVersionNumbers(); + int32_t version = sOSVersion.load(std::memory_order_relaxed); + if (version != 0) { + return version; } - return mOSVersion; + + // Compute the version. Multiple threads might do the computation + // concurrently. That's ok; they will all compute the same value. + version = ComputeVersion(); + if (version != 0) { + sOSVersion.store(version, std::memory_order_relaxed); + } + + return version; } /* static */ int32_t nsCocoaFeatures::macOSVersionMajor() {