Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fix #15394
The os_unfair_lock is causing a deadlock due to its lack of recursion support. Fixed by replacing it with NSRecursiveLock in UnfairLock.swift. This involves updating the import, properties, and lock/unlock methods to use the new recursive lock, while keeping the public API unchanged.
The core of the problem, as indicated by the stack trace, is a deadlock occurring within FirebaseCoreInternal.UnfairLock. This UnfairLock is a low-level locking primitive used by various Firebase modules, including Firebase Sessions.
The stack trace clearly shows:
FirebaseSessions/Sources/Settings/RemoteSettings.swift).
The issue arises because os_unfair_lock (which UnfairLock was wrapping) is not recursive. If the main thread attempts to acquire this lock while it already holds it (due to nested calls or multiple observers being triggered by the same event, like app foregrounding), it will deadlock.
✦ That's a very important question. A recursive lock behaves differently from a non-recursive one, and it's crucial to ensure this change doesn't introduce unintended side effects.
I'll investigate all usages of UnfairLock in the codebase to determine if any of them rely on the non-recursive behavior. My plan is as follows:
I'll start by finding all occurrences of "UnfairLock". │
│ Found 42 matches │
✦ The search results show UnfairLock is used across several Firebase modules (Functions, AI, Sessions, Auth, Core) primarily for safeguarding mutable properties.
Here's my analysis of the usage patterns:
The original crash was caused by a deadlock when different parts of the Sessions module, both responding to foregrounding notifications, tried to acquire the same non-recursive lock.
Given these observations, changing to a recursive lock is a safe and correct fix. It solves the deadlock problem without creating new issues because the existing code doesn't rely on the non-recursive behavior. The recursive lock will simply continue to work for simple cases and prevent deadlocks in the more complex re-entrant scenarios that were causing your crash.