#!/bin/sh
# Safe replacement for a bare `cinnamon --replace` recovery command.
#
# 2026-08-07 root cause: the desktop froze because the compositor ended up
# inside app.slice (capped, pids.max=8000) instead of the login session scope
# (session-N.scope, uncapped) — a fork bomb elsewhere in app.slice starved
# the whole slice, and cinnamon itself could no longer fork. `systemd-run
# --user <cmd>` places transient services in app.slice by default; that is
# exactly how a bare recovery invocation reproduces the same trap.
#
# A process cannot escape UPWARD out of its own cgroup subtree without root —
# login session scopes are not systemd-delegated, so there is no unprivileged
# "start it anywhere, then reparent it" trick (verified: both
# AttachProcessesToUnit and a raw cgroup.procs write are refused for a
# non-root caller). The only unprivileged fix is to never leave the safe
# cgroup in the first place: run this from a shell that is ALREADY inside a
# session-N.scope (any real login shell — a TTY console, or a terminal that
# is itself not agent/app-slice-launched) and let the child inherit it, with
# no systemd-run wrapping at all.
set -eu

own_cgroup=$(cut -d: -f3 < /proc/self/cgroup)
case "$own_cgroup" in
  */session-*.scope)
    ;;
  *)
    cat >&2 <<EOF
cinnamon-safe-recover: refusing to start — this shell's own cgroup is
  $own_cgroup
not a login session scope, so cinnamon would inherit the SAME unsafe
placement and there is no unprivileged way to move it afterward.

Run this from a real login shell instead: switch to a text console
(Ctrl+Alt+F2), log in, then run this script there. A console login shell is
always inside its own session-N.scope, which cinnamon will inherit safely.
EOF
    exit 1
    ;;
esac

setsid /usr/bin/cinnamon --replace >/dev/null 2>&1 < /dev/null &
disown
echo "cinnamon-safe-recover: cinnamon started as pid $! inside $own_cgroup"
