From 178e3d69f1e6db7df05f546c660c87fc47d75e16 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Thu, 27 Nov 2025 16:00:56 -0800 Subject: [PATCH 1/3] Fix UnfairLock deadlock --- FirebaseCore/CHANGELOG.md | 2 ++ .../Sources/Utilities/UnfairLock.swift | 36 +++++-------------- Gemfile | 1 + 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/FirebaseCore/CHANGELOG.md b/FirebaseCore/CHANGELOG.md index 49629fa233b..b87251e28b5 100644 --- a/FirebaseCore/CHANGELOG.md +++ b/FirebaseCore/CHANGELOG.md @@ -3,6 +3,8 @@ resolves build failures when using static linking (`use_frameworks! :linkage => :static`) in projects using frameworks like React Native (#15506). +- [fixed] Fix UnfairLock deadlock that is known to occur from Crashlytics or + Performance. (#15394) # Firebase 12.0.0 - [changed] **Breaking change**: Firebase's minimum supported versions have diff --git a/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift b/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift index 9028029763c..26c918793cf 100644 --- a/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift +++ b/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift @@ -1,3 +1,4 @@ + // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,54 +14,35 @@ // limitations under the License. import Foundation -private import os.lock -/// A reference wrapper around `os_unfair_lock`. Replace this class with -/// `OSAllocatedUnfairLock` once we support only iOS 16+. For an explanation -/// on why this is necessary, see the docs: -/// https://developer.apple.com/documentation/os/osallocatedunfairlock +/// A thread-safe wrapper around a value. public final class UnfairLock: @unchecked Sendable { - private var lockPointer: UnsafeMutablePointer + private var lock: NSRecursiveLock = .init() private var _value: Value public init(_ value: consuming sending Value) { - lockPointer = UnsafeMutablePointer - .allocate(capacity: 1) - lockPointer.initialize(to: os_unfair_lock()) _value = value } - deinit { - lockPointer.deallocate() - } - public func value() -> Value { - lock() - defer { unlock() } + lock.lock() + defer { lock.unlock() } return _value } @discardableResult public borrowing func withLock(_ body: (inout sending Value) throws -> sending Result) rethrows -> sending Result { - lock() - defer { unlock() } + lock.lock() + defer { lock.unlock() } return try body(&_value) } @discardableResult public borrowing func withLock(_ body: (inout sending Value) -> sending Result) -> sending Result { - lock() - defer { unlock() } + lock.lock() + defer { lock.unlock() } return body(&_value) } - - private func lock() { - os_unfair_lock_lock(lockPointer) - } - - private func unlock() { - os_unfair_lock_unlock(lockPointer) - } } diff --git a/Gemfile b/Gemfile index cc267b2e746..7143ab933f1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,6 @@ # To update, change version below, run bundle install, test, # commit Gemfile and Gemfile.lock. +#touch source 'https://rubygems.org' # To test CocoaPods pre-releases, update to a relevant commit or tag like below From c0b947a47ce247295bc7a49a2233c2aecfae4ca0 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Thu, 27 Nov 2025 16:30:49 -0800 Subject: [PATCH 2/3] Restore Gemfile after good test run --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index 7143ab933f1..cc267b2e746 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,5 @@ # To update, change version below, run bundle install, test, # commit Gemfile and Gemfile.lock. -#touch source 'https://rubygems.org' # To test CocoaPods pre-releases, update to a relevant commit or tag like below From 5a9c7b6ae73f27177a0c8a907973eb4eb4a509fb Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Fri, 28 Nov 2025 07:23:35 -0800 Subject: [PATCH 3/3] Remove extra blank line --- FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift b/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift index 26c918793cf..b3c0f53a4c0 100644 --- a/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift +++ b/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift @@ -1,4 +1,3 @@ - // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License");