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..b3c0f53a4c0 100644 --- a/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift +++ b/FirebaseCore/Internal/Sources/Utilities/UnfairLock.swift @@ -13,54 +13,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) - } }