Deadlock analysis
Skill Amey-Thakur/AI-SKILLS/skills/debugging/deadlock-analysis
Find why threads are stuck forever by dumping their state and building the wait-for graph that reveals the lock cycle. Use when a program hangs with no progress and no crash, or throughput drops to zero while CPU sits idle.From its SKILL.md
npx -y skills add Amey-Thakur/AI-SKILLS --skill deadlock-analysisAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 23 days oldThe repository was created 23 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.0 KB, 684 tokens by cl100k_base, as published. Nobody here has run it
Deadlock analysis
A deadlock is a cycle of waiting: thread A holds lock 1 and wants lock 2 while thread B holds lock 2 and wants lock 1, and neither will ever move. The process is not crashed, it is frozen, which fools you into looking for a slow operation instead of a stuck one. The cycle is always visible in a thread dump if you know how to read the waits.
Method
- Confirm it is a deadlock, not slowness. Idle CPU with zero progress for minutes points at blocking, not computation. A busy CPU spinning forever is a livelock or infinite loop, a different bug. Check that threads are parked in a wait state, not running hot.
- Capture a thread dump at the moment of the hang.
jstack <pid>orkill -3on the JVM,py-spy dump --pidfor Python,dlvorSIGQUITfor Go (which prints all goroutine stacks),gdb -p <pid>thenthread apply all btfor native. Take two dumps a few seconds apart: if the stacks are identical, nothing is moving. - Read who holds what and who waits for what. A good dump names it directly: the JVM prints "Found one Java-level deadlock" with the lock ids, "waiting to lock <0x...>" versus "locked <0x...>". For each blocked thread, write down the lock it holds and the lock it wants.
- Draw the wait-for graph and find the cycle. Nodes are threads, an edge runs from a thread to the thread holding the lock it waits on. A cycle in that graph is the deadlock, and the locks on the cycle are the ones acquired in conflicting order. Two locks is the common case; the graph scales to more.
- Fix with a global lock ordering. Pick a total order for the locks on
the cycle (by address, by name, by a fixed rank) and make every code path
acquire them in that order. If ordering is impractical, use a single
coarser lock, a
tryLockwith timeout and backoff, or lock-free structures. Consistent order breaks every cycle by construction. - Prove it under contention. Run the path that hung under many threads
for an extended loop. A deadlock that reproduced in minutes should now run
indefinitely. Static tools help catch regressions:
-Xlint,jcstress, or Clang's-Wthread-safetyannotations flag out-of-order acquisition.
Signals
- Do two thread dumps taken seconds apart show identical, parked stacks?
- Can you trace a closed cycle through the wait-for graph?
- Does every path that touches those locks now take them in one fixed order?
Boundaries
This covers mutual-exclusion deadlocks between threads in one process. Distributed deadlocks across services, database lock waits, and connection- pool exhaustion wear the same mask but resolve with transaction timeouts, lock ordering at the database, or pool sizing, not with a thread dump.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.