| name | csa-async-debug |
| description | Expert diagnosis for Tokio/async Rust issues including deadlocks, task leaks, performance bottlenecks, and cancellation safety |
| allowed-tools | Bash, Read, Grep, Glob |
Async/Tokio Debugging Guide
Expert diagnosis for Tokio/async Rust issues: deadlocks, task leaks, performance bottlenecks, and cancellation safety.
Common Async Anti-Patterns
1. Blocking the Runtime
async fn bad() {
std::thread::sleep(Duration::from_secs(1));
std::fs::read_to_string("file");
}
async fn good() {
tokio::time::sleep(Duration::from_secs(1)).await;
tokio::fs::read_to_string("file").await;
tokio::task::spawn_blocking(|| expensive_cpu_work()).await;
}
2. Deadlocks (Lock Held Across Await)
async fn deadlock() {
let lock = mutex.lock().await;
some_async_fn().await;
drop(lock);
}
async fn safe() {
let data = {
let lock = mutex.lock().await;
lock.clone()
};
some_async_fn().await;
}
3. Task Leaks
fn leak() {
tokio::spawn(async { ... });
}
let mut set = JoinSet::new();
set.spawn(task1());
set.spawn(task2());
while let Some(result) = set.join_next().await { ... }
4. Cancellation Unsafety
async fn unsafe_cancel() {
file.write_all(header).await?;
file.write_all(body).await?;
}
async fn safe_cancel() {
let temp = create_temp_file().await?;
temp.write_all(data).await?;
temp.rename(target).await?;
}
Diagnosis Tools
Tokio-Console
Runtime Metrics
let metrics = tokio::runtime::Handle::current().metrics();
println!("Active tasks: {}", metrics.active_tasks_count());
println!("Blocking threads: {}", metrics.num_blocking_threads());
Debug Process
- Collect Evidence: Error logs, tokio-console output, timing info
- Locate Problem: Which await point hangs? Which blocking call?
- Analyze Root Cause: Deadlock graph, cancellation paths, resource contention
- Verify Fix: Stress test with high concurrency, long-running tests
Checklist for Async Code