Merge pull request #2228 from MilhouseVH/le90_safe_mode

kodi: safe mode [RFC]
This commit is contained in:
CvH 2017-12-14 19:01:15 +01:00 committed by GitHub
commit 9155531c28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 130 additions and 14 deletions

View File

@ -17,8 +17,8 @@
################################################################################
PKG_NAME="LibreELEC-settings"
PKG_VERSION="85b86d4"
PKG_SHA256="944f0984f96234e81ae79a595942d830c9554b39c8be8ca287a3c4ff8930c695"
PKG_VERSION="057ab16"
PKG_SHA256="dac3e653a5348e3dcd229399343e7a78fa9123e1c721c2a2117d43967f354354"
PKG_ARCH="any"
PKG_LICENSE="prop."
PKG_SITE="https://libreelec.tv"

View File

@ -265,8 +265,14 @@ post_makeinstall_target() {
mkdir -p $INSTALL/usr/lib/kodi
cp $PKG_DIR/scripts/kodi-config $INSTALL/usr/lib/kodi
cp $PKG_DIR/scripts/kodi-safe-mode $INSTALL/usr/lib/kodi
cp $PKG_DIR/scripts/kodi.sh $INSTALL/usr/lib/kodi
# Configure safe mode triggers - default 5 restarts within 900 seconds/15 minutes
$SED -e "s|@KODI_MAX_RESTARTS@|${KODI_MAX_RESTARTS:-5}|g" \
-e "s|@KODI_MAX_SECONDS@|${KODI_MAX_SECONDS:-900}|g" \
-i $INSTALL/usr/lib/kodi/kodi.sh
mkdir -p $INSTALL/usr/sbin
cp $PKG_DIR/scripts/service-addon-wrapper $INSTALL/usr/sbin

View File

@ -17,28 +17,35 @@
# along with OpenELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
KODI_ROOT=$HOME/.kodi
BOOT_STATE="$(cat $HOME/.config/boot.status 2>/dev/null)"
# hack: make addon-bins executable
# done in kodi on addon install. but just in case..
chmod +x /storage/.kodi/addons/*/bin/*
chmod +x $KODI_ROOT/addons/*/bin/* 2>/dev/null
# hack: update RSSnews.xml in userdata
if [ -f /storage/.kodi/userdata/RssFeeds.xml ]; then
if [ -f $KODI_ROOT/userdata/RssFeeds.xml ]; then
sed -e "s,http://libreelec.tv/news?format=feed&type=rss,http://feeds.libreelec.tv/news,g" \
-i /storage/.kodi/userdata/RssFeeds.xml
-i $KODI_ROOT/userdata/RssFeeds.xml
fi
# setup Kodi sources
if [ ! -f $HOME/.kodi/userdata/sources.xml ]; then
if [ ! -f $KODI_ROOT/userdata/sources.xml ]; then
if [ -f /usr/share/kodi/config/sources.xml ]; then
cp /usr/share/kodi/config/sources.xml $HOME/.kodi/userdata
cp /usr/share/kodi/config/sources.xml $KODI_ROOT/userdata
fi
fi
# common setup guisettings
if [ ! -f $HOME/.kodi/userdata/guisettings.xml ] ; then
if [ ! -f $KODI_ROOT/userdata/guisettings.xml ] ; then
if [ -f /usr/share/kodi/config/guisettings.xml ]; then
cp /usr/share/kodi/config/guisettings.xml $HOME/.kodi/userdata
cp /usr/share/kodi/config/guisettings.xml $KODI_ROOT/userdata
fi
if [ "$BOOT_STATE" = "SAFE" ]; then
[ ! -f $KODI_ROOT/userdata/guisettings.xml ] && echo '<settings version="2"></settings>' > $KODI_ROOT/userdata/guisettings.xml
xmlstarlet ed --omit-decl --inplace -s settings -t elem -n setting -v "maroon" -i settings/setting -t attr -n id -v lookandfeel.skincolors $KODI_ROOT/userdata/guisettings.xml
fi
fi

View File

@ -0,0 +1,49 @@
#!/bin/sh
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2016-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
KODI_ROOT=$HOME/.kodi
KODI_ROOT_FAILED=$KODI_ROOT.FAILED
BOOT_STATUS=$HOME/.config/boot.status
process_boot_status()
{
BOOT_STATE="$(cat $BOOT_STATUS 2>/dev/null)"
if [ "${BOOT_STATE}" = "SAFE" ]; then
if [ ! -d $KODI_ROOT_FAILED ]; then
# entering safe mode - rename failed .kodi, and restart with clean .kodi
mv $KODI_ROOT $KODI_ROOT_FAILED
reboot
else
# exiting safe mode - restore failed .kodi
rm -fr $KODI_ROOT
mv $KODI_ROOT_FAILED $KODI_ROOT
echo "OK" > $BOOT_STATUS
fi
else
echo "OK" > $BOOT_STATUS
fi
return 0
}
process_boot_status
exit 0

View File

@ -16,8 +16,16 @@
trap cleanup TERM
KODI_ROOT=$HOME/.kodi
SAVED_ARGS="$@"
CRASHLOG_DIR=/storage/.kodi/temp
CRASHLOG_DIR=$KODI_ROOT/temp
BOOT_STATUS=$HOME/.config/boot.status
NOSAFE_MODE=$HOME/.config/safemode.disable
CRASH_HIST=/run/libreelec/crashes.dat
KODI_MAX_RESTARTS=@KODI_MAX_RESTARTS@
KODI_MAX_SECONDS=@KODI_MAX_SECONDS@
cleanup() {
# make systemd happy by not exiting immediately but
@ -43,6 +51,41 @@ single_stacktrace()
done
}
detect_crash_loop()
{
# use monotonic time (in case date/time changes after booting)
NOW_TIME=$(awk '/^now/ {print int($3 / 1000000000)}' /proc/timer_list)
echo "$NOW_TIME" >> $CRASH_HIST
NUM_RESTARTS=$(wc -l $CRASH_HIST | cut -d' ' -f1)
FIRST_RESTART_TIME=$(tail -n $MAX_RESTARTS $CRASH_HIST | head -n 1)
# kodi restart loop detected? fail this kodi install
if [ $NUM_RESTARTS -ge $KODI_MAX_RESTARTS -a $KODI_MAX_SECONDS -ge $((NOW_TIME - FIRST_RESTART_TIME)) ]; then
return 0
else
return 1
fi
}
activate_safe_mode()
{
[ -f $NOSAFE_MODE ] && return 0
BOOT_STATE="$(cat $BOOT_STATUS 2>/dev/null)"
if [ "${BOOT_STATE:-OK}" = "OK" ]; then
# generate logfiles zip for the failed kodi
/usr/bin/createlog
lastlog=$(ls -1 /storage/logfiles/*.zip | tail -n 1)
mv $lastlog /storage/logfiles/log-$(date -u +%Y-%m-%d-%H.%M.%S)-FAILED.zip
echo "SAFE" > $BOOT_STATUS
fi
return 0
}
print_crash_report()
{
mkdir -p $CRASHLOG_DIR
@ -74,7 +117,7 @@ print_crash_report()
echo >> $FILE
echo "################# LOG FILE ##################" >> $FILE
echo >> $FILE
cat /storage/.kodi/temp/kodi.log >> $FILE
cat $KODI_ROOT/temp/kodi.log >> $FILE
echo >> $FILE
echo "############### END LOG FILE ################" >> $FILE
echo >> $FILE
@ -82,7 +125,7 @@ print_crash_report()
OFILE="$FILE"
FILE="$CRASHLOG_DIR/kodi_crashlog_$DATE.log"
mv "$OFILE" "$FILE"
ln -sf "$FILE" "$CRASHLOG_DIR/kodi_crash.log"
ln -sf "$(basename $FILE)" "$CRASHLOG_DIR/kodi_crash.log"
echo "Crash report available at $FILE"
}
@ -94,8 +137,10 @@ fi
find /storage/.cache/cores -type f -delete
# clean zero-byte database files that prevent migration/startup
for file in /storage/.kodi/userdata/Database/*.db; do
[ -s $file ] || rm -f $file
for file in $KODI_ROOT/userdata/Database/*.db; do
if [ -e "$file" ]; then
[ -s $file ] || rm -f $file
fi
done
/usr/lib/kodi/kodi.bin $SAVED_ARGS
@ -107,6 +152,9 @@ if [ $(( ($RET >= 131 && $RET <= 136) || $RET == 139 )) = "1" ] ; then
# Cleanup. Keep only youngest 10 reports
rm -f $(ls -1t $CRASHLOG_DIR/kodi_crashlog_*.log | tail -n +11)
# Enable safe mode if a crash loop is detected
detect_crash_loop && activate_safe_mode
fi
exit $RET

View File

@ -16,6 +16,7 @@ EnvironmentFile=-/run/libreelec/debug/kodi.conf
ExecStartPre=-/usr/lib/kodi/kodi-config
ExecStart=/usr/lib/kodi/kodi.sh --standalone -fs $KODI_ARGS $KODI_DEBUG
ExecStop=/bin/kill -TERM $MAINPID
ExecStopPost=-/usr/lib/kodi/kodi-safe-mode
TimeoutStopSec=5
Restart=always
RestartSec=2

View File

@ -40,6 +40,11 @@ if [ "$SAMBA_AUTOSHARE" == "true" ] ; then
done
fi
# Allow access to a "failed" (safe mode) Kodi installation
if [ -d /storage/.kodi.FAILED ]; then
echo -e "[Kodi-Failed]\n path = /storage/.kodi.FAILED\n available = yes\n browsable = yes\n public = yes\n writable = yes\n" >> $SMB_CONF
fi
ADD_CONFIG=
# If workgroup is not set, don't set it - who knows, user may know better.