3 # This script parses /proc/locks and finds the processes that are holding
4 # locks on CTDB databases. For all those processes the script dumps a
7 # This script can be used only if Samba is configured to use fcntl locks
8 # rather than mutex locks.
10 [ -n "$CTDB_BASE" ] || \
11 CTDB_BASE
=$
(d
=$
(dirname "$0") ; cd -P "$d" ; echo "$PWD")
13 .
"${CTDB_BASE}/functions"
15 # type is at least mentioned in POSIX and more is portable than which(1)
16 # shellcheck disable=SC2039
17 if ! type gstack
>/dev
/null
2>&1 ; then
22 gdb
-batch --quiet -nx "/proc/${_pid}/exe" "$_pid" \
23 -ex "thread apply all bt" 2>/dev
/null |
24 grep '^\(#\|Thread \)'
28 # Load/cache database options from configuration file
34 echo "===== Start of debug locks PID=$$ ====="
36 # Create sed expression to convert inodes to names.
37 # Filenames don't contain dashes and we want basenames
38 # shellcheck disable=SC2035
39 sed_cmd
=$
(cd "$CTDB_DBDIR" &&
40 stat
-c "s#[0-9a-f]*:[0-9a-f]*:%i #%n #" *.tdb.
* 2>/dev
/null
;
41 cd "$CTDB_DBDIR_PERSISTENT" &&
42 stat
-c "s#[0-9a-f]*:[0-9a-f]*:%i #%n #" *.tdb.
* 2>/dev
/null
)
44 # Parse /proc/locks and extract following information
45 # pid process_name tdb_name offsets [W]
46 out
=$
( grep -F "POSIX ADVISORY WRITE" /proc
/locks |
47 awk '{ if($2 == "->") { print $6, $7, $8, $9, "W" } else { print $5, $6, $7, $8 } }' |
48 while read pid rest
; do
49 pname
=$
(readlink
"/proc/${pid}/exe")
50 echo "$pid $pname $rest"
51 done |
sed -e "$sed_cmd" |
grep '\.tdb' )
53 if [ -n "$out" ]; then
54 # Log information about locks
57 # Find processes that are waiting for locks
58 dbs
=$
(echo "$out" |
grep "W$" |
awk '{print $3}')
61 pids
=$
(echo "$out" |
grep -v "W$" |
grep "$db" |
grep -v ctdbd |
awk '{print $1}')
62 all_pids
="$all_pids $pids"
64 # Use word splitting to squash whitespace
65 # shellcheck disable=SC2086
66 pids
=$
(echo $all_pids |
tr ' ' '\n' |
sort -u)
68 # For each process waiting, log stack trace
70 echo "----- Stack trace for PID=$pid -----"
71 # x is intentionally ignored
72 # shellcheck disable=SC2034
73 read x x state x
<"/proc/${pid}/stat"
74 if [ "$state" = "D" ] ; then
75 # Don't run gstack on a process in D state since
76 # gstack will hang until the process exits D state.
77 # Although it is possible for a process to transition
78 # to D state after this check, it is unlikely because
79 # if a process is stuck in D state then it is probably
80 # the reason why this script was called. Note that a
81 # kernel stack almost certainly won't help diagnose a
82 # deadlock... but it will probably give us someone to
84 echo "----- Process in D state, printing kernel stack only"
85 cat "/proc/${pid}/stack"
92 echo "===== End of debug locks PID=$$ ====="
93 )9>"${CTDB_SCRIPT_VARDIR}/debug_locks.lock" | script_log
"ctdbd-lock"