fix(display-service): HOME/WorkingDirectory fuer lgpio unter systemd setzen

Am Pi diagnostiziert: unter systemd ist HOME leer und cwd "/", lgpio legt seine
Benachrichtigungs-Pipe aber unter "$HOME/.lgd-nfy0" an - das wird "//.lgd-nfy0"
und scheitert an ProtectSystem=strict. gpiozero faellt bis zur experimentellen
NativeFactory durch, die dann mit EINVAL abbricht; display.py faengt das als
DisplayUnavailable ab und beendet sich mit 0, sodass der Ausfall wie ein
fehlendes Panel aussieht statt wie die eigentliche Sandbox-Ursache.

RuntimeDirectory=ninlight-display, WorkingDirectory= und Environment=HOME=
zeigen jetzt auf ein eigenes, beschreibbares /run/ninlight-display - bewusst
getrennt vom RuntimeDirectory der Hauptunit, da dieser Dienst dort nur liest.

Szenario 19 in test_setup_pi.sh prueft die drei Zeilen in der ausgelieferten
Unit; per Mutationsprobe bestaetigt, dass das Entfernen jeder einzelnen davon
den Test rot werden laesst.
This commit is contained in:
Michael Sauer
2026-09-14 01:32:53 +02:00
parent 47532a6820
commit 46b0a198d9
2 changed files with 59 additions and 0 deletions
+23
View File
@@ -33,6 +33,29 @@ Environment=NINLIGHT_STATION_CONF=/etc/ninlight-station.conf
# trotzdem (mit den Environment=-Vorgaben oben) statt mit einem harten Fehler - "die
# Anzeige darf nirgends Voraussetzung sein" gilt auch fuer ihre eigene Konfiguration.
EnvironmentFile=-/etc/ninlight-station.conf
# RuntimeDirectory=/WorkingDirectory=/Environment=HOME= zusammen beheben einen Fund aus
# der Hardware-Abnahme: lgpio (gpiozero's bevorzugte Pin-Factory) legt beim Start eine
# Benachrichtigungs-Pipe unter "$HOME/.lgd-nfy0" an. Unter systemd ist HOME per Vorgabe
# LEER und das Arbeitsverzeichnis "/" - der Pfad wird "//.lgd-nfy0", und ProtectSystem=
# strict (unten) macht "/" schreibgeschuetzt. lgpio scheitert dann mit "Can't set
# permissions", gpiozero faellt ueber rpigpio/pigpio bis zur experimentellen NativeFactory
# durch, und DIE scheitert ihrerseits mit [Errno 22] Invalid argument - display.py faengt
# das korrekt als DisplayUnavailable ab und beendet sich mit 0 (siehe Kommentar zu
# Restart=on-failure unten), aber das Panel bleibt schwarz und das Journal sieht aus wie
# "kein Panel angeschlossen", obwohl die Hardware in Ordnung ist. Am Geraet nachgemessen
# (systemd-run mit denselben zwei Property=, gegen ein Shell-echo von $HOME und pwd).
#
# RuntimeDirectory=ninlight-display ist ABSICHTLICH ein eigenes Verzeichnis, nicht das
# RuntimeDirectory=ninlight-station der Hauptunit: dieser Dienst liest von dort nur
# (status.json/control.json ueber NINLIGHT_RUN_DIR, s.o.), er soll dort nichts anlegen
# koennen. Schriebe die Anzeige in fremden Laufzeitzustand, waere das eine unnoetige
# Kopplung an dessen Lebenszyklus (siehe die Begruendung zu ReadOnlyPaths= weiter unten:
# server.py's RuntimeDirectory wird beim Stop/Neustart geleert). systemd legt
# /run/ninlight-display beim Start dieser Unit selbst an (Vorgabe 0755, vom User dieses
# Dienstes - hier root, s.u. - beschreibbar) und raeumt es beim Stop wieder auf.
RuntimeDirectory=ninlight-display
WorkingDirectory=/run/ninlight-display
Environment=HOME=/run/ninlight-display
ExecStart=/usr/bin/python3 /opt/ninlight-station/display/display.py
# display.py faengt ein fehlendes/abgestuerztes Panel als DisplayUnavailable ab,