deadlock(8)
๐ deadlock(8) ๐
System Manager's Manual โจ
โจ NAME โจ
deadlock is the tea-spilling tool for finding potential deadlocks (lock order inversions) in a running program ๐๐
๐ง SYNOPSIS ๐ง
deadlock [-h] [--binary BINARY] [--dump-graph DUMP_GRAPH] [--verbose]
[--lock-symbols LOCK_SYMBOLS] [--unlock-symbols UNLOCK_SYMBOLS] pid
๐ฆ DESCRIPTION ๐ฆ
okay so deadlock is literally a detective for a running process ๐ต๏ธโโ๏ธ By default it attaches uprobes on pthread_mutex_lock and pthread_mutex_unlock and uses them to build a mutex wait directed graph. Then it checks that graph for a cycle. The graph has these vibes:
- Nodes in the graph represent mutexes. ๐
- Edge (A, B) exists if there exists some thread T where lock(A) was called and lock(B) was called before unlock(A) was called. ๐งต
If there's a cycle in the graph, that means there's a lock order inversion, aka a potential deadlock ๐ญ When the program catches one, it dumps the cycle of mutexes, dumps the stack traces showing where each mutex was acquired, and then exits. bye bye ๐
Heads up bestie: this program can only find potential deadlocks that happen while it's tracing the process. It cannot find deadlocks that may have occurred before the program was attached to the process. ๐
This tool does not work for shared mutexes or recursive mutexes. Not for those, sorry ๐ โโ๏ธ
Since this uses BPF, only the root user can use this tool. ๐
๐ REQUIREMENTS ๐
You'll need CONFIG_BPF and bcc โจ
๐ OPTIONS ๐
-h,--helpโ show this help message and exit ๐โโ๏ธ--binary BINARYโ If set, trace the mutexes from the binary at this path. For statically-linked binaries, this argument is not required. For dynamically-linked binaries, this argument is required and should be the path of the pthread library the binary is using. Example:/lib/x86_64-linux-gnu/libpthread.so.0๐--dump-graph DUMP_GRAPHโ If set, this will dump the mutex graph to the specified file. ๐พ--verboseโ Print statistics about the mutex wait graph. ๐--lock-symbols LOCK_SYMBOLSโ Comma-separated list of lock symbols to trace. Default ispthread_mutex_lock. These symbols cannot be inlined in the binary. ๐--unlock-symbols UNLOCK_SYMBOLSโ Comma-separated list of unlock symbols to trace. Default ispthread_mutex_unlock. These symbols cannot be inlined in the binary. ๐-t THREADS,--threads THREADSโ Sets the maximum number of threads to trace. Default is 65536. Note: that's 40 bytes per thread ๐งต-e EDGES,--edges EDGESโ Sets the maximum number of edge cases that can be recorded. Default is 65536. Note: that's 88 bytes per edge case ๐ฆpidโ Pid to trace ๐ฏ
๐ธ EXAMPLES ๐ธ
Find potential deadlocks in PID 181. The --binary argument is not needed for statically-linked binaries, so you can just do this:
# deadlock 181
Find potential deadlocks in PID 181. If the process was created from a dynamically-linked executable, the --binary argument is required and must be the path of the pthread library:
# deadlock 181 --binary /lib/x86_64-linux-gnu/libpthread.so.0
Find potential deadlocks in PID 181. If the process was created from a statically-linked executable, you can optionally pass the location of the binary. On older kernels without https://lkml.org/lkml/2017/1/13/585, binaries that contain : in the path cannot be attached with uprobes. The workaround is to make a symlink to the binary and pass the symlink name with the --binary option instead:
# deadlock 181 --binary /usr/local/bin/lockinversion
Find potential deadlocks in PID 181 and dump the mutex wait graph to a file:
# deadlock 181 --dump-graph graph.json
Find potential deadlocks in PID 181 and print mutex wait graph statistics:
# deadlock 181 --verbose
Find potential deadlocks in PID 181 with custom mutexes:
# deadlock 181 --lock-symbols
custom_mutex1_lock,custom_mutex2_lock --unlock_symbols
custom_mutex1_unlock,custom_mutex2_unlock
๐ฎ OUTPUT ๐ฎ
This program doesn't output any fields, bestie. It just keeps running until it finds a potential deadlock or you hit Ctrl-C โณ If it does find one, it prints the stack traces and the lock order inversion in the format below, and then exits:
Potential Deadlock Detected!
Cycle in lock order graph: Mutex M0 => Mutex M1 => Mutex M0
Mutex M1 acquired here while holding Mutex M0 in Thread T:
[stack trace]
Mutex M0 previously acquired by the same Thread T here:
[stack trace]
Mutex M0 acquired here while holding Mutex M1 in Thread S:
[stack trace]
Mutex M1 previously acquired by the same Thread S here:
[stack trace]
Thread T created by Thread R here:
[stack trace]
Thread S created by Thread Q here:
[stack trace]
๐ข OVERHEAD ๐ข
This traces all mutex lock and unlock events and all thread creation events on the traced process. It can get pretty laggy if the process has lots of threads and mutexes ๐ฉ Only run this on a process where the slowdown is acceptable.
๐ SOURCE ๐
This is from bcc ๐
https://github.com/iovisor/bcc
Also check out the bcc distribution for a companion _examples.txt file with example usage, output, and commentary for this tool ๐
๐ง OS ๐ง
Linux ๐ง
๐ซ STABILITY ๐ซ
Unstable - in development. ๐ง
๐ AUTHOR ๐
Kenny Yu ๐ซถ
Bye bestie! ๐ That's the whole tea: this is a USER COMMANDS page, dated 2017-02-01, all about deadlock(8) ๐ฆโจ
๐ฆ where this page comes from
- alpine 3.24: bcc-doc 0.36.1-r1 ยท Apache-2.0
- nixpkgs unstable: bcc 0.37.0
- opensuse-leap 16.0: bcc-tools 0.35.0-160000.2.2 ยท Apache-2.0
- opensuse-leap 16.0: bcc-tools 0.35.0-160000.2.2 ยท Apache-2.0
- opensuse-leap 16.0: bcc-tools 0.35.0-160000.2.2 ยท Apache-2.0
- opensuse-leap 16.0: bcc-tools 0.35.0-160000.2.2 ยท Apache-2.0
- ๐ girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms