-
Notifications
You must be signed in to change notification settings - Fork 60
Description
Summary
We are encountering a crash due to an _os_unfair_lock_corruption_abort in the HTTPFields._Storage.copy() method from the Swift HTTP Types package. The crash appears to be related to concurrent mutations of an HTTPFields instance when used in our dynamic XCFramework. This issue seems to occur when the copy-on-write (COW) mechanism (using isKnownUniquelyReferenced) does not properly handle concurrent access, causing the internal os_unfair_lock to become corrupted.
Description
Our project uses Swift HTTP Types for managing HTTP header fields (via the HTTPFields struct). In our usage, we update header fields in our middleware which eventually calls into the subscript setter of HTTPFields and invokes setFields(_:). Internally, this causes a copy-on-write operation on the _Storage class.
The _Storage class uses an os_unfair_lock (allocated via an UnsafeMutablePointer<os_unfair_lock>) to protect its internal index and fields. During a call to _Storage.copy(), we observe that the lock is corrupted, leading to a call to _os_unfair_lock_corruption_abort.
A brief excerpt from our stack trace is as follows:
Thread 5 Queue : com.apple.root.user-initiated-qos.cooperative (concurrent)
#0 0x00000001f691c220 in _os_unfair_lock_corruption_abort ()
#1 0x00000001f6919578 in _os_unfair_lock_lock_slow ()
#2 0x000000010367fc2c in HTTPFields._Storage.copy() at HTTPFields.swift:92
Our current hypothesis is that when the same HTTPFields instance is mutated concurrently by multiple threads, the copy-on-write mechanism (which checks uniqueness via isKnownUniquelyReferenced) does not provide proper synchronization. This concurrent access causes the internal os_unfair_lock to be used in an unsafe manner (or even be copied), eventually resulting in the reported corruption.
Steps to Reproduce
1. Use the Swift HTTP Types package (via SPM) along with Swift Open API Runtime.
2. Integrate these packages into a dynamic XCFramework.
3. In a scenario where header fields (using HTTPFields) are mutated concurrently—for example, in a middleware that updates header fields from multiple concurrent operations—observe that the app crashes with _os_unfair_lock_corruption_abort.
Note: Building as a static XCFramework is not viable due to duplicate symbol errors, which forces us to use a dynamic XCFramework.
Expected Behavior
HTTPFields should be safe to use in concurrent scenarios or should at least clearly document that instances must not be mutated concurrently. Alternatively, internal synchronization (or a different COW strategy) might be needed to prevent the os_unfair_lock from becoming corrupted when a copy is triggered under concurrent mutations.
Workaround
Until a fix is provided, we are serializing access to any shared HTTPFields instance in our middleware to avoid concurrent mutations. This has mitigated the issue in our code but may not be ideal in all use cases.
Additional Context
• We have verified that the crash occurs in HTTPFields._Storage.copy() during the locking operation.
• The problem may be exacerbated by the fact that our project uses a dynamic XCFramework, leading to potential multiple loads or copies of the same SPM package code.
Any guidance or fixes on making the copy-on-write mechanism (and the use of os_unfair_lock) in HTTPFields safe under concurrent access would be greatly appreciated.
Thank you for your attention to this matter.