mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-19 17:39:06 +00:00
On a 1GB Pi 3B+ the display process settles around 600MB RSS of 905MB total. When the remaining headroom runs out the failure is not a clean crash: fork() starts returning ENOMEM, so sshd accepts connections and closes them before its banner, timer jobs stop running, and the panel goes dark, while already-resident processes keep serving normally. The board looks healthy from outside and cannot be logged into. Only a power cycle clears it. Three contributing causes: - MemoryCache had a fixed 1000-entry ceiling. Entries are parsed API payloads of tens of KB, so one ceiling cannot serve both a 512MB Zero 2 W and an 8GB Pi 5. Now scaled from MemTotal (150 entries at <=1GB, 1500 at >=8GB), overridable with LEDMATRIX_CACHE_MAX_ENTRIES. - requirements_are_satisfied() returned False for any requirement with extras, so a plugin depending on python-socketio[client] re-ran pip on every single start: ~8s, a network dependency, and a 100-200MB spike at the least convenient moment. During a restart loop it repeats for each restart. Extras are now resolved one level deep against installed metadata, keeping the conservative "anything unverifiable falls through to pip" contract. - ledmatrix.service had no memory ceiling. MemoryMax=85% expressed as a percentage so one unit file suits every board. Note this needs the memory cgroup controller, which Pi firmware disables by default; first_time_install.sh now adds cgroup_enable=memory to cmdline.txt, and the unit file documents how to verify it took effect. first_time_install.sh also enables persistent journald storage (capped at 64M). Default storage is volatile, so every reboot destroys the logs that would explain why the board rebooted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
41 lines
1.7 KiB
Desktop File
41 lines
1.7 KiB
Desktop File
[Unit]
|
|
Description=LED Matrix Display Service
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=root
|
|
WorkingDirectory=__PROJECT_ROOT_DIR__
|
|
Environment=PYTHONDONTWRITEBYTECODE=1
|
|
ExecStart=/usr/bin/python3 __PROJECT_ROOT_DIR__/run.py
|
|
# Restart=always, not on-failure: run.py exiting 0 (a clean shutdown path taken
|
|
# for a reason that no longer applies, e.g. a config reload) would otherwise leave
|
|
# the service stopped and the panel dark indefinitely, with systemd considering
|
|
# that a successful outcome and never bringing it back.
|
|
Restart=always
|
|
RestartSec=10
|
|
# Memory ceiling as a share of physical RAM, so one unit file suits a 512 MB
|
|
# Pi Zero 2 W and an 8 GB Pi 5 alike. This is a backstop, not a tuning knob: it
|
|
# turns "the board runs out of memory, stops being able to fork, and takes sshd
|
|
# and the panel down together until someone pulls the plug" into "this one
|
|
# service restarts".
|
|
#
|
|
# NOTE: Raspberry Pi firmware boots the kernel with cgroup_disable=memory, and
|
|
# systemd accepts this setting and then silently ignores it. Verify with:
|
|
# grep memory /sys/fs/cgroup/cgroup.controllers
|
|
# If that prints nothing, add "cgroup_enable=memory cgroup_memory=1" to
|
|
# /boot/firmware/cmdline.txt (all on line 1) and reboot. first_time_install.sh
|
|
# does this for you.
|
|
MemoryMax=85%
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
SyslogIdentifier=ledmatrix
|
|
# Support for on-demand plugin filtering via environment variable
|
|
# The environment variable LEDMATRIX_ON_DEMAND_PLUGIN can be set via:
|
|
# sudo systemctl set-environment LEDMATRIX_ON_DEMAND_PLUGIN=<plugin_id>
|
|
# Or by using an EnvironmentFile (see below)
|
|
# EnvironmentFile=__PROJECT_ROOT_DIR__/config/on_demand_env.conf
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target |