#!/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"