diff --git a/packages/mediacenter/LibreELEC-settings/package.mk b/packages/mediacenter/LibreELEC-settings/package.mk
index 3ea50de679..13d3bd47cc 100644
--- a/packages/mediacenter/LibreELEC-settings/package.mk
+++ b/packages/mediacenter/LibreELEC-settings/package.mk
@@ -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"
diff --git a/packages/mediacenter/kodi/package.mk b/packages/mediacenter/kodi/package.mk
index ff26714b0a..bbb6531437 100644
--- a/packages/mediacenter/kodi/package.mk
+++ b/packages/mediacenter/kodi/package.mk
@@ -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
diff --git a/packages/mediacenter/kodi/scripts/kodi-config b/packages/mediacenter/kodi/scripts/kodi-config
index a8586b8d3b..b5a55ac48e 100755
--- a/packages/mediacenter/kodi/scripts/kodi-config
+++ b/packages/mediacenter/kodi/scripts/kodi-config
@@ -17,28 +17,35 @@
# along with OpenELEC. If not, see .
################################################################################
+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 '' > $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
diff --git a/packages/mediacenter/kodi/scripts/kodi-safe-mode b/packages/mediacenter/kodi/scripts/kodi-safe-mode
new file mode 100755
index 0000000000..35506c4e02
--- /dev/null
+++ b/packages/mediacenter/kodi/scripts/kodi-safe-mode
@@ -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 .
+################################################################################
+
+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
diff --git a/packages/mediacenter/kodi/scripts/kodi.sh b/packages/mediacenter/kodi/scripts/kodi.sh
index 5972aedad8..be89abb0f4 100755
--- a/packages/mediacenter/kodi/scripts/kodi.sh
+++ b/packages/mediacenter/kodi/scripts/kodi.sh
@@ -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
diff --git a/packages/mediacenter/kodi/system.d/kodi.service b/packages/mediacenter/kodi/system.d/kodi.service
index d6d0250037..e09747bfd1 100644
--- a/packages/mediacenter/kodi/system.d/kodi.service
+++ b/packages/mediacenter/kodi/system.d/kodi.service
@@ -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
diff --git a/packages/network/samba/scripts/smbd-config b/packages/network/samba/scripts/smbd-config
index a3df4ddc85..d381ae8c0b 100755
--- a/packages/network/samba/scripts/smbd-config
+++ b/packages/network/samba/scripts/smbd-config
@@ -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.