-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Crash in Swift 6.1 when using async let inside a do {} block (Xcode 16.3+) #81771
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
Comments
I want to report an interesting finding regarding the crash described here. If I use async let to concurrently fetch two values, then await them, and then use the results to map into an array of model objects (especially when assigning to a property that may be observed/@published), the process often crashes with “freed pointer was not the last allocation”. However, if I wrap the entire async let/await block inside an inner closure and return a tuple (containing the array and other values), the crash no longer occurs—even though the logic and data are exactly the same. Here’s a minimal reproduction:
I suspect this is due to a difference in how memory is managed across the async let stack frame and the closure’s context, but I hope this helps others reproduce the issue and clarify what is happening! |
i'd be interested to see more info about the example, like the signatures of the involved types & functions. i tried a simplified reduction and could not reproduce the problem locally. additionally i'd be curious to know whether running the offending code with either the address or thread sanitizer enabled yields any additional information as to what could be going wrong. |
Are you able to put together a complete example? (Reduced would be nice, but a large project that replicates the issue would be great too, if possible.) I tried adapting your code above but they don't crash when I add some stubs to make them build. The basic issue here is that the generated code allocates memory on the async task stack, then deallocates that memory out of order. This can be caused by issues in the code such as throwing ObjC exceptions through async Swift code, but in this case it looks likely to be a compiler bug. The changes you mention that fix the issue probably convince the compiler to deallocate the memory in the proper order. |
I ran both address sanitizer and thread sanitizer, but neither produced any relevant logs. That said, I do agree that this is likely a compiler bug.
This pattern seems to cause a crash when the
By moving the async let inside an await { ... } block, the crash no longer occurs. This reinforces the idea that the original crash is caused by the compiler generating incorrect deallocation logic for Let me know if there’s anything else I can provide to help investigate further. |
Yeah, if it's what I suspect, then the issue is that the compiler-emitted calls should be:
But are actually:
Sanitizers won't help with that, since everything is fine in terms of basic memory access and thread safety. Are you able to provide the full project? A non-minimal reproducer would be helpful too. Otherwise, I'll keep an eye on this and see if I can figure anything out. The good news is that this should be consistent in any given binary. If you run down this particular code path and it doesn't encounter this error once, then you know it's doing things in the right order and is solid, so you can have confidence in your workarounds at least. |
This issue doesn’t always reproduce consistently, even within the same project — it seems to depend on the specific screen or code path. |
Understood, often these things can't be shared. Hopefully we can track it down one way or another. I appreciate all the info so far. |
Description
In Swift 6.1 (Xcode 16.3 and 16.4), placing
async let
bindings inside a do block causes a runtime crash—even when those values are properly awaited and the code is enclosed in do-catch. The crash does not occur in Xcode 16.2 or earlier.This behavior seems to be related to how task deallocation is handled for
async let
when declared inside lexical scopes.Reproduction
Stack dump
Expected behavior
async let
declared inside a do block should behave the same as when declared outside it, as long as all values are awaited. It should not result in a crash.Environment
swift-driver version: 1.120.5 Apple Swift version 6.1.2 (swiftlang-6.1.2.1.2 clang-1700.0.13.5)
Target: arm64-apple-macosx15.0
Additional information
This may be a regression introduced by recent changes to task deallocation logic in Swift 6.1. The crash appears related to how async let scopes are finalized when declared in lexical blocks like do {}.
The text was updated successfully, but these errors were encountered: