dotfiles/.local/bin/gnome-shell-restart

75 lines
2.1 KiB
Shell
Executable file

#!/bin/sh
# Restart `gnome-shell` in place,
# preserving the session and all windows
#
# Usually survives, but treat it like a logout:
# save your work first, because a crash on the way down can end the session
#
# Debian normally forbids starting/stopping this unit by hand;
# we allow it via a user-level drop-in (installed on first run)
set -eu
if [ "${XDG_SESSION_TYPE:-}" != "x11" ]; then
echo "gnome-shell-restart: only works on X11, not on ${XDG_SESSION_TYPE:-unknown}" >&2
exit 1
fi
_UNIT="org.gnome.Shell@x11.service"
_DROPIN_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/$_UNIT.d"
_DROPIN_FILE="$_DROPIN_DIR/allow-restart.conf"
if [ ! -f "$_DROPIN_FILE" ] || ! grep -q "SuccessExitStatus" "$_DROPIN_FILE"; then
mkdir -p "$_DROPIN_DIR"
cat > "$_DROPIN_FILE" << 'EOF'
# Written by ~/.local/bin/gnome-shell-restart
# Debian forbids starting and stopping this unit by hand
# to protect Wayland sessions, where the shell cannot restart in place
# => We are on X11
[Unit]
RefuseManualStart=no
RefuseManualStop=no
# The old shell sometimes crashes while shutting down.
#
# Without this line, `systemd` treats that crash as a real failure
# and ends the whole session (i.e., logs us out)
#
# => We count a segfault as a normal exit
#
# If the shell truly keeps crashing, the start limit still ends the session
[Service]
SuccessExitStatus=1 SEGV
EOF
systemctl --user daemon-reload
fi
# The unit allows at most 3 starts per 15 seconds
# and one restart too many counts as a failure and logs us out
# => Refuse to restart again too soon after the last one
_STARTED="$(systemctl --user show -p ActiveEnterTimestamp --value "$_UNIT")"
if [ -n "$_STARTED" ]; then
_AGE=$(( $(date +%s) - $(date -d "$_STARTED" +%s) ))
if [ "$_AGE" -lt 20 ]; then
echo "gnome-shell-restart: last shell start was only ${_AGE}s ago" >&2
echo "gnome-shell-restart: refusing to trip the start limit (wait $(( 20 - _AGE ))s)" >&2
exit 1
fi
fi
# Forget any earlier failure, so it does not block this restart
systemctl --user reset-failed "$_UNIT" 2> /dev/null || true
exec systemctl --user restart "$_UNIT"