Guard is held across a disallowed await
Rule ID: concurrency.guard-held-across-suspension@1.0.0. Availability below refers to source-scan at product 524fa07e.
V-ASYNC-14 — Guard is held across a disallowed await#
Holding a synchronous guard across an await can violate its allowed suspension or thread-affinity contract and prevent other work from making progress.
Availability#
Selected by default in source-scan. Selection does not mean a supported observation exists in your program.
Use the terminal from Installation, with ANALYZER set. Replace <package> and <product> with your supported package path and product name.
"$ANALYZER" source-scan --package-path <package> --product <product> --allow-buildExample and action#
Reproduced as part of the first-analysis package at product 524fa07e on Apple Swift 6.3.3, macOS arm64. Read the complete example before running it.
import Foundation
private let gate = NSLock()
private func enter() { gate.lock() }
private func leave() { gate.unlock() }
func perform() async { enter(); await Task.yield(); leave() }The control releases the guard before suspension. In a real application, copy the necessary state under the guard and revalidate it before applying a later result. Moving release is not safe if the operation requires a stronger state protocol.
import Foundation
private let gate = NSLock()
private func enter() { gate.lock() }
private func leave() { gate.unlock() }
func perform() async { enter(); leave(); await Task.yield() }Why this check works#
The check follows recognized guard acquisition, suspension and release events in an admitted trace. An acquired guard that survives the disallowed suspension supplies a witness. The tutorial produces one such finding and also an incomplete trace; both are preserved in the degraded report.
Assumptions and unknown#
The source mapper does not model every lock wrapper or synchronization primitive. Missing events, unclear guard identity or an incomplete trace preserve unknown. A witness in one trace does not establish completeness of another trace.
Evidence and interpretation#
Read condition coverage, observation counts and reasons in the actual report. A finding and an unknown observation can coexist. No observations is not a negative proof.
Historical evidence at 4558458d: recovery-required (historical qualification is incomplete and needs further evidence). That evidence has not been requalified for this product revision.
How we validate checks explains the evidence boundary. Foundations separates method assumptions from implementation claims.