diff --git a/configs/baseline/airootfs/root/.xinitrc b/configs/baseline/airootfs/root/.xinitrc
index d9c898d..46f06bd 100644
--- a/configs/baseline/airootfs/root/.xinitrc
+++ b/configs/baseline/airootfs/root/.xinitrc
@@ -34,22 +34,84 @@ if command -v liveinst >/dev/null 2>&1; then
mount --bind /run/archiso/airootfs /run/rootfsbase || rmdir /run/rootfsbase
fi
+ # GARDE-FOU RAM : le live n'a que le zram comme marge — en dessous de
+ # ~2 Go, Anaconda (GUI Python + squashfs) peut geler la machine en plein
+ # « Préparation de l'installateur ». On prévient AVANT plutôt que de
+ # laisser l'utilisateur croire à un bug.
+ _MEMKB=$(awk '/^MemTotal:/{print $2}' /proc/meminfo 2>/dev/null)
+ if [ -n "$_MEMKB" ] && [ "$_MEMKB" -lt 2000000 ] && command -v zenity >/dev/null 2>&1; then
+ zenity --warning --width=460 --title="FWS — mémoire insuffisante ?" \
+ --text="Cette machine n'a que $(( _MEMKB / 1024 )) Mo de RAM.\n\nL'installateur graphique peut geler en dessous de 2 Go.\nEn VM : augmente la mémoire (4 Go recommandés) puis redémarre.\n\nOK pour tenter quand même." 2>/dev/null
+ fi
+
# ÉCRAN D'ATTENTE immédiat : le démarrage d'anaconda peut prendre 2 à
# 4 minutes (observé en VM VMware : un worker udev se bloque au boot et
- # n'est tué par udevd qu'après 180 s → le « udevadm settle » d'anaconda
- # attend tout ce temps). Sans feedback, l'écran reste bleu et muet et
- # l'utilisateur croit à une panne (« l'installateur ne se lance pas »)
- # alors que TOUT va bien. Le splash pulse pendant la préparation ;
- # anaconda s'ouvre PAR-DESSUS quand il est prêt (openbox donne le focus
- # aux nouvelles fenêtres) et on tue le splash à la sortie de liveinst.
- # tail -f /dev/null : zenity --progress lit stdin — un stdin qui ne se
- # ferme jamais garde la fenêtre ouverte sans consommer de CPU.
+ # n'est tué par udevd qu'après 45 s — udev.event_timeout). Sans feedback,
+ # l'utilisateur croit à une panne alors que TOUT va bien. Le splash montre
+ # EN DIRECT ce que fait anaconda : un nourrisseur écrit sur stdin de
+ # zenity --progress (« # texte » = mise à jour du libellé) le log anaconda
+ # le plus récemment modifié + son dernier message + un chrono. Si les logs
+ # ne bougent plus (vrai blocage), le libellé le DIT (au lieu d'une barre
+ # qui pulse pour rien) et, au-delà de 4 min d'inactivité, on collecte
+ # journal+dmesg dans /tmp/fws-stall.txt et on l'affiche : l'écran devient
+ # lui-même le rapport de bug. Le nourrisseur meurt par SIGPIPE quand le
+ # splash est tué à la sortie de liveinst.
_SPLASH_PID=""
if command -v zenity >/dev/null 2>&1; then
- tail -f /dev/null | zenity --progress --pulsate --no-cancel \
+ (
+ _el=0; _quiet=0; _prevstamp=""
+ while :; do
+ sleep 3
+ # GUI d'anaconda à l'écran (marqueur ui.gui) → le splash n'a
+ # plus de raison d'être et le watchdog DOIT se désarmer : des
+ # logs silencieux pendant que l'utilisateur remplit les écrans
+ # sont NORMAUX (bug vécu : le rapport « préparation bloquée »
+ # s'affichait PAR-DESSUS l'installateur au bout de 4 min).
+ if grep -q 'ui\.gui' /tmp/anaconda.log 2>/dev/null; then
+ pkill -f 'zenity --progress' 2>/dev/null
+ exit 0
+ fi
+ # Compteurs en itérations (pas d'heure murale : l'horloge du
+ # guest SAUTE en VM — resynchro RTC — et gonflerait les âges,
+ # vu en vrai : « 242 s d'inactivité » 90 s après le boot).
+ _el=$(( _el + 3 ))
+ _last=$(ls -t /tmp/storage.log /tmp/anaconda.log /tmp/program.log /tmp/dbus.log 2>/dev/null | head -n1)
+ if [ -z "$_last" ]; then
+ printf '# Démarrage d'"'"'Anaconda… (%d min %02d s)\n' $(( _el / 60 )) $(( _el % 60 )) || exit 0
+ continue
+ fi
+ _stamp=$(stat -c %Y "$_last" 2>/dev/null)
+ if [ "$_stamp" = "$_prevstamp" ]; then
+ _quiet=$(( _quiet + 3 ))
+ else
+ _quiet=0; _prevstamp="$_stamp"
+ fi
+ # Rebranding d'affichage : anaconda (installateur Fedora) parle
+ # de Fedora/Arch dans ses logs — on ne montre pas ça à l'écran.
+ _msg=$(tail -n1 "$_last" 2>/dev/null | tr -d '\r' \
+ | sed -E 's/Fedora( Linux)?/FWS/g; s/Arch Linux/FWS/g; s/\/FWS/g' \
+ | cut -c1-90)
+ if [ "$_quiet" -ge 240 ] && [ ! -f /tmp/fws-stall.txt ]; then
+ {
+ echo "=== FWS : préparation bloquée (aucune activité log depuis ${_quiet}s) ==="
+ echo "--- dernier log actif : $_last"; tail -n 25 "$_last" 2>/dev/null
+ echo "--- udev (workers bloqués ?)"; udevadm settle --timeout=0 2>&1
+ echo "--- journal (fin)"; journalctl -b --no-pager 2>/dev/null | tail -n 60
+ echo "--- dmesg (fin)"; dmesg 2>/dev/null | tail -n 40
+ } > /tmp/fws-stall.txt 2>&1
+ zenity --text-info --title="FWS — préparation bloquée : diagnostic" \
+ --filename=/tmp/fws-stall.txt --width=1000 --height=650 2>/dev/null &
+ fi
+ if [ "$_quiet" -ge 60 ]; then
+ printf '# ⚠ Aucune activité depuis %d s (%s) — dernier message : %s\n' "$_quiet" "$(basename "$_last")" "$_msg" || exit 0
+ else
+ printf '# Préparation (%d min %02d s) — %s : %s\n' $(( _el / 60 )) $(( _el % 60 )) "$(basename "$_last")" "$_msg" || exit 0
+ fi
+ done
+ ) | zenity --progress --pulsate --no-cancel \
--title="FWS" \
--text="Préparation de l'installateur FWS…\n\nAnalyse du matériel et des disques en cours.\nEncore une à deux minutes, c'est normal." \
- --width=420 2>/dev/null &
+ --width=560 2>/dev/null &
_SPLASH_PID=$!
fi
@@ -64,6 +126,16 @@ if command -v liveinst >/dev/null 2>&1; then
/usr/share/anaconda/ui/hubs/summary.glade 2>/dev/null || true
fi
+ # BRANDING : sans /.buildstamp, anaconda s'appelle « anaconda bluesky »
+ # (défauts de pyanaconda/core/product.py) et ses logs parlent de Fedora.
+ # Les variables d'environnement ANACONDA_* ont priorité → l'en-tête
+ # devient « FWS 1.0 INSTALLATION » et le log « anaconda … for FWS started ».
+ # (Les mentions Fedora PROFONDES dans les logs — GeoIP, profils — restent :
+ # ce sont des chaînes internes de l'installateur, sans effet sur l'install.)
+ export ANACONDA_PRODUCTNAME="$(. /etc/os-release 2>/dev/null; echo "${NAME:-FWS}")"
+ export ANACONDA_PRODUCTVERSION="$(. /etc/os-release 2>/dev/null; echo "${VERSION_ID:-1.0}")"
+ export ANACONDA_ISFINAL=true
+
LIVEINST_LOG=/tmp/fws-liveinst.log
# Bus D-Bus de SESSION : au démarrage (--liveinst), inhibit_screensaver()
# de pyanaconda se connecte au bus de session. S'il n'y en a AUCUN (notre
@@ -80,11 +152,13 @@ if command -v liveinst >/dev/null 2>&1; then
rc=$?
# liveinst terminé (install finie ou échec) : le splash n'a plus de raison
- # d'être — kill du pipeline tail|zenity (pkill -P attrape les deux).
+ # d'être — kill de zenity ; le nourrisseur meurt de SIGPIPE à son
+ # prochain printf. Idem pour un éventuel dialogue de diagnostic de stall.
if [ -n "$_SPLASH_PID" ]; then
pkill -P "$_SPLASH_PID" 2>/dev/null
kill "$_SPLASH_PID" 2>/dev/null
fi
+ pkill -f "fws-stall.txt" 2>/dev/null
# ATTENTION : liveinst NE propage PAS le code de sortie d'anaconda — il
# enchaîne son propre nettoyage et sort souvent 0 même quand anaconda a