I wrote a technical walkthrough of a subtle Swift Concurrency issue I wanted to explore.
Imagine a task writing data into a buffered writer. The task gets cancelled, defer runs, and close() gets called. But if close()invokes a cancellation-aware flush(), that flush can throw CancellationError. If the error is swallowed and the writer is marked closed anyway, the cleanup path has run without achieving its intended postcondition.
The article explores two Swift Evolution proposals:
- SE-0493: Async calls in
defer bodies
- SE-0504: Task Cancellation Shields
It covers a minimal reproduction, the limits of using Task.detached for cleanup, a narrowly scoped cancellation shield, and a Swift Testing example that checks whether the data was actually flushed rather than merely checking whether close() was called.
One important caveat: the example demonstrates a cancellation-aware cleanup failure, not a claim that every real file API corrupts data when cancelled.
Full article: https://sagarsaurav.medium.com/the-ios-task-was-cancelled-your-defer-still-didnt-flush-the-file-a81d45b02ad9?sharedUserId=sagarsaurav
I'd be interested in feedback on the cancellation-shield approach, especially around resource ownership and cleanup guarantees in production code.