Overview
Async and concurrency bugs are the hardest class of bugs to debug because they're non-deterministic — they appear and disappear based on timing that varies between runs. Adding logging to investigate them often changes the timing enough to make them disappear (a Heisenbug). The diagnosis approach must be adapted to this non-determinism: instead of trying to reproduce the exact failure, the goal is to identify the invariant that the race condition violates, and enforce that invariant.
The Async Debugging Framework identifies the type of concurrency bug, designs diagnostic approaches that don't change the timing, and implements fixes that eliminate the race rather than making it less likely.