#!/bin/sh # # This is a wrapper script (based on kodi/xbmc script) to monitor subsurface and get debug information using GDB when a crash happens. # Informations are stored in *.log file in CRASHLOG_DIR ($HOME by default) APP=Subsurface bin_name=subsurface SAVED_ARGS="$@" prefix="/usr" CRASHLOG_DIR=${CRASHLOG_DIR:-$HOME} APP_VERSION=$(${prefix}/bin/${bin_name} --version) command_exists() { command -pv $1 >/dev/null 2>&1 } single_stacktrace() { # core filename is either "core.$PID" or "core" find "$1" -maxdepth $2 -name 'core*' | while read core; do LC_ALL=C gdb --core="$core" --batch 2> /dev/null | grep -q "^Core was generated by \`${prefix}/bin/${bin_name}" || continue echo "=====> Core file: "$core" ($(stat -c%y "$core"))" >> $FILE echo " =========================================" >> $FILE gdb "${prefix}/bin/${bin_name}" --core="$core" --batch -ex "thread apply all bt" 2> /dev/null >> $FILE rm -f "$core" done } print_crash_report() { FILE="$CRASHLOG_DIR/${bin_name}_crashlog-`date +%Y%m%d_%H%M%S`.log" echo "############## $APP CRASH LOG ###############" >> $FILE echo >> $FILE echo "################ SYSTEM INFO ################" >> $FILE echo -n " Date: " >> $FILE LC_ALL=C date >> $FILE echo " $APP Options: $SAVED_ARGS" >> $FILE echo " $APP version: $APP_VERSION" >> $FILE echo -n " Arch: " >> $FILE uname -m >> $FILE echo -n " Kernel: " >> $FILE uname -rvs >> $FILE echo -n " Release: " >> $FILE if [ -f /etc/os-release ]; then . /etc/os-release echo $NAME $VERSION >> $FILE elif command_exists lsb_release; then echo >> $FILE lsb_release -a 2> /dev/null | sed -e 's/^/ /' >> $FILE else echo "lsb_release not available" >> $FILE fi echo "############## END SYSTEM INFO ##############" >> $FILE echo >> $FILE echo "############### STACK TRACE #################" >> $FILE if command_exists gdb; then # TODO: systemd needs more test (systemd-coredumpctl exist on openSUSE 13.1 but does not find any core) # if command_exists systemd-coredumpctl; then # systemd-coredumpctl dump -o core ${prefix}/bin/${bin_name} > /dev/null 2>&1 # elif command_exists coredumpctl; then # coredumpctl dump -o core ${prefix}/bin/${bin_name} > /dev/null 2>&1 # fi # Find in current directory single_stacktrace "$PWD" 1 # Find in plugins directories if [ $KODI_HOME ]; then BASEDIR=$KODI_HOME else BASEDIR="$LIBDIR/${bin_name}/" fi single_stacktrace "$BASEDIR" 5 # find in userdata dir single_stacktrace "$HOME" 5 # try /proc/sys/kernel/core_pattern [ -d "$(dirname $(cat /proc/sys/kernel/core_pattern))" ] && single_stacktrace "$(dirname $(cat /proc/sys/kernel/core_pattern))" 1 else echo "gdb not installed, can't get stack trace." >> $FILE fi echo "############# END STACK TRACE ###############" >> $FILE echo >> $FILE echo "############ END $APP CRASH LOG #############" >> $FILE echo "Crash report available at $FILE" } if command_exists gdb; then # Output warning in case ulimit is unsupported by shell eval ulimit -c unlimited if [ ! $? = "0" ]; then echo "${bin_name}: ulimit is unsupported by this shell" 1>&2 fi fi LOOP=1 while [ $(( $LOOP )) = "1" ] do LOOP=0 "${prefix}/bin/${bin_name}" $SAVED_ARGS RET=$? if [ $(( $RET == 65 )) = "1" ] then # User requested to restart app LOOP=1 elif [ $(( ($RET >= 131 && $RET <= 136) || $RET == 139 )) = "1" ] then # Crashed with core dump print_crash_report fi # echo "RET = $RET" done exit $RET