mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
4628afa3f5
gstack isn't widely available, so provide a simple function that does the same thing if it gstack can't be found. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com> Autobuild-User(master): Amitay Isaacs <amitay@samba.org> Autobuild-Date(master): Wed Jul 11 14:47:21 CEST 2018 on sn-devel-144
96 lines
3.0 KiB
Bash
Executable File
96 lines
3.0 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# This script parses /proc/locks and finds the processes that are holding
|
|
# locks on CTDB databases. For all those processes the script dumps a
|
|
# stack trace.
|
|
#
|
|
# This script can be used only if Samba is configured to use fcntl locks
|
|
# rather than mutex locks.
|
|
|
|
[ -n "$CTDB_BASE" ] || \
|
|
CTDB_BASE=$(d=$(dirname "$0") ; cd -P "$d" ; echo "$PWD")
|
|
|
|
. "${CTDB_BASE}/functions"
|
|
|
|
# type is at least mentioned in POSIX and more is portable than which(1)
|
|
# shellcheck disable=SC2039
|
|
if ! type gstack >/dev/null 2>&1 ; then
|
|
gstack ()
|
|
{
|
|
_pid="$1"
|
|
|
|
gdb -batch --quiet -nx "/proc/${_pid}/exe" "$_pid" \
|
|
-ex "thread apply all bt" 2>/dev/null |
|
|
grep '^\(#\|Thread \)'
|
|
}
|
|
fi
|
|
|
|
# Load/cache database options from configuration file
|
|
ctdb_get_db_options
|
|
|
|
(
|
|
flock -n 9 || exit 1
|
|
|
|
echo "===== Start of debug locks PID=$$ ====="
|
|
|
|
# Create sed expression to convert inodes to names.
|
|
# Filenames don't contain dashes and we want basenames
|
|
# shellcheck disable=SC2035
|
|
sed_cmd=$(cd "$CTDB_DBDIR" &&
|
|
stat -c "s#[0-9a-f]*:[0-9a-f]*:%i #%n #" *.tdb.* 2>/dev/null ;
|
|
cd "$CTDB_DBDIR_PERSISTENT" &&
|
|
stat -c "s#[0-9a-f]*:[0-9a-f]*:%i #%n #" *.tdb.* 2>/dev/null)
|
|
|
|
# Parse /proc/locks and extract following information
|
|
# pid process_name tdb_name offsets [W]
|
|
out=$( grep -F "POSIX ADVISORY WRITE" /proc/locks |
|
|
awk '{ if($2 == "->") { print $6, $7, $8, $9, "W" } else { print $5, $6, $7, $8 } }' |
|
|
while read pid rest ; do
|
|
pname=$(readlink "/proc/${pid}/exe")
|
|
echo "$pid $pname $rest"
|
|
done | sed -e "$sed_cmd" | grep '\.tdb' )
|
|
|
|
if [ -n "$out" ]; then
|
|
# Log information about locks
|
|
echo "$out"
|
|
|
|
# Find processes that are waiting for locks
|
|
dbs=$(echo "$out" | grep "W$" | awk '{print $3}')
|
|
all_pids=""
|
|
for db in $dbs ; do
|
|
pids=$(echo "$out" | grep -v "W$" | grep "$db" | grep -v ctdbd | awk '{print $1}')
|
|
all_pids="$all_pids $pids"
|
|
done
|
|
# Use word splitting to squash whitespace
|
|
# shellcheck disable=SC2086
|
|
pids=$(echo $all_pids | tr ' ' '\n' | sort -u)
|
|
|
|
# For each process waiting, log stack trace
|
|
for pid in $pids ; do
|
|
echo "----- Stack trace for PID=$pid -----"
|
|
# x is intentionally ignored
|
|
# shellcheck disable=SC2034
|
|
read x x state x <"/proc/${pid}/stat"
|
|
if [ "$state" = "D" ] ; then
|
|
# Don't run gstack on a process in D state since
|
|
# gstack will hang until the process exits D state.
|
|
# Although it is possible for a process to transition
|
|
# to D state after this check, it is unlikely because
|
|
# if a process is stuck in D state then it is probably
|
|
# the reason why this script was called. Note that a
|
|
# kernel stack almost certainly won't help diagnose a
|
|
# deadlock... but it will probably give us someone to
|
|
# blame!
|
|
echo "----- Process in D state, printing kernel stack only"
|
|
cat "/proc/${pid}/stack"
|
|
else
|
|
gstack "$pid"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
echo "===== End of debug locks PID=$$ ====="
|
|
)9>"${CTDB_SCRIPT_VARDIR}/debug_locks.lock" | script_log "ctdbd-lock"
|
|
|
|
exit 0
|