-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
os_unfair_lock Corruption in HTTPFields Storage Copy Under Concurrent Mutation #86
Comments
Thanks for filing this issue. Can you show us the usage site of the HTTP fields? I'm concerned that this is more likely to be a thread-safety issue in user code. |
To elaborate, if you have written a middleware that operates concurrently from multiple threads, you must not mutate a stored HTTPFields object from concurrent threads without synchronization. Swift 6 mode will diagnose this for you immediately. |
Hi, Thank you for your response. After further investigation, we found that even when we comment out all direct usage of HTTPFields in our own code, the crash still occurs within the Swift OpenAPI Runtime module. Specifically, the crash occurs when the OpenAPI Generator–produced code is built into a dynamic XCFramework and integrated into our project. Here are our observations: These findings suggest that the issue is not due to our middleware mutating HTTPFields from multiple threads without proper synchronization, but rather it seems to be related to the dynamic framework loading mechanism. It appears that in this scenario, the internal os_unfair_lock within HTTPFields may be subject to concurrent access issues or even duplication, leading to the reported lock corruption. Since using dynamic frameworks is necessary for our project (due to duplicate symbol issues with static frameworks), we are looking for a more robust solution. Could you provide any additional guidance on: Thank you for your attention and assistance. |
Can you say more about how you're building the xcframework(s)? swift-http-types and swift-openapi-runtime are two distinct modules, are you building two distinct xcframeworks? Or are you building both modules into the same xcframework? |
Are you using all of the operations from the OpenAPI document in your code? If not, you might instead want to opt into using filtering, and only generate/compile what you're using. That usually helps with the build time concerns. Since both Swift HTTP Types and Swift OpenAPI Runtime produce public APIs, it will be tricky to build individual xcframeworks and get it all working. I'd strongly recommend sticking with the plugin (or manual generation), rather than building the xcframework as a way to speed up builds. |
I’m already using the |
Build times and caching are being looked at by the folks working on SwiftPM, as it affects all packages. But yes, in the meantime, I'd recommend avoiding the xcframework. cc @dschaefer2 |
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:
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
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
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.
The text was updated successfully, but these errors were encountered: