Swift 6.4: Task Cancellation Shields

|

SE-0504 adds withTaskCancellationShield — a way to run a closure where Task.isCancelled always returns false, regardless of the outer task’s cancellation state.

The problem it solves: cleanup and rollback work that must finish even when a task has been cancelled. Without a shield, awaits inside cancelled tasks can skip or short-circuit unexpectedly.

func closeConnection() async {
    await withTaskCancellationShield {
        await database.close()   // runs to completion even if outer task is cancelled
    }
    // Task.isCancelled reflects the real state again here
}

A good one-two punch is pairing it with defer:

func performWork() async throws {
    defer {
        withTaskCancellationShield {
            cleanup()   // deferred cleanup that must not be skipped
        }
    }
    try await doTheWork()
}

The shield also prevents cancellation from propagating into child tasks — async let bindings and task groups inside the closure won’t be automatically cancelled.

Constraints worth knowing:

  • Keep shielded regions short — finish or roll back work already started, not hide cancellation from long-running operations
  • Once the closure returns, the outer task’s cancellation state is restored

Takeaway: reach for withTaskCancellationShield when you have cleanup that cannot be skipped on cancellation — it’s the missing piece for reliable resource teardown in structured concurrency.

← Back to DevLog
rss facebook twitter github youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora