1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
#!/bin/bash
#
# This script dumps the Prolog stacks of a running SWI-Prolog process
# It requires SWI-Prolog 7.3.31 and a gdb, the GNU debugger.
#
# Author: Jan Wielemaker
#
# This code is in the public domain
btflags=0
btdepth=10
thread=pid
stack=prolog
out=
usage()
{ echo "Dump stacks of a running SWI-Prolog process"
echo
echo "Usage: $(basename $0) [options] pid"
echo "Options"
echo " --depth=N Print max N goals (default 10)"
echo " --thread=N Only print thread N (default from pid)"
echo " --safe Do not try to print predicate arguments"
echo " --user Only print user predicates"
echo " --info Print thread info"
echo " -C Print the C stack (default Prolog)"
echo " --out=file Also write result to file"
}
done=false
while [ $done = false ]; do
case "$1" in
--depth=*)
btdepth=$(echo $1 | sed 's/--depth=//')
shift
;;
--thread=*)
thread=$(echo $1 | sed 's/--thread=//')
shift
;;
--out=*)
out=$(eval echo $(echo $1 | sed 's/--out=//'))
shift
;;
--safe)
btflags=$(($btflags|1))
shift
;;
--user)
btflags=$(($btflags|2))
shift
;;
--info)
stack=info
shift
;;
--*)
usage
exit 1
;;
-C)
stack=C
shift
;;
*)
done=true
;;
esac
done
if [[ "$1" =~ ^[0-9]+$ ]]; then
pid=$1
else
usage
exit 1
fi
if [ "$thread" = pid ]; then
cmd=
else
cmd="thread apply $thread "
fi
case "$stack" in
C)
cmd+=bt
;;
prolog)
cmd+='printf "%s\n", (char*)PL_backtrace_string('$btdepth,$btflags')'
;;
info)
cmd="info threads"
esac
gdb </dev/null --nx --batch \
-ex "set pagination off" -ex "set height 0" -ex "set width 0" \
-ex "set print thread-events off" \
-ex "handle SIGUSR2 nostop noprint pass" \
-ex "attach $pid" \
-ex "$cmd" \
-ex detach -ex quit | tee $out
|