Repository navigation
Stop cleanly on SIGTERM, as systemd and Docker stop a service - #224
AnjinMeili wants to merge 1 commit into
Conversation
`systemctl stop`, `docker stop` and `kill` now stop MoonLight the way Ctrl+C does: every driver releases its output, so a HUB75 panel goes dark rather than freezing lit, and the service stops at once rather than after systemd's 90-second timeout. **Core** - main_desktop.cpp: SIGTERM gets its own handler, the same clean stop as SIGINT. Not one-shot: a service manager escalates to SIGKILL itself, so a second SIGTERM must not cut the stop short. - The stop flag is `volatile std::sig_atomic_t`, the one type a signal handler may write and the main thread read: `mm_main`'s signature and the flag in main_desktop.cpp, esp32/main/main.cpp and teensy/main.cpp. - main_desktop.cpp: its comments are one line each, within docgen's rules, since the file was touched. **Docs/CI** - build-system.md: the desktop entry point handles SIGINT and SIGTERM; `mm_main(keepRunning, httpPort)` is its signature; the ESP32 entry point initializes NVS, not Ethernet. - moonwalk/02-install.yaml: `sudo systemctl stop moonlight` stops MoonLight cleanly. - src/main.cpp's 17 docgen warnings are its boot-tree comment, outside this change. - check_prose: NegatedHeading 6 to 8 and SelfReference 16 to 17 are main's baseline: the committed tree measures the same with this change absent. **Tests** - No unit test reaches a signal handler. Verified on the Pi 5 bench: `systemctl stop` darkens the panels and returns at once. - test_desktop: 2,875 passed on macOS and the Pi 5 (whole branch). **Reviews** - SIGTERM shared the one-shot SIGINT handler and its Ctrl+C hint: done, its own handler. - `volatile bool` as the flag a handler writes: done, `sig_atomic_t`. - The Windows `signal(SIGTERM)` line: done, removed, since Windows never raises SIGTERM. - build-system.md named the old `mm_main` signature: done. - build-system.md said the ESP32 entry point starts Ethernet: done, NVS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
There was a problem hiding this comment.
🟡 Changes recommended
The shutdown flag still permits a critical C++ data race between the main thread and workers handling SIGTERM or SIGINT because volatile std::sig_atomic_t does not synchronize threads.
1 open issue
What changed in this PR
This PR routes desktop SIGTERM requests through MoonLight’s existing shutdown path so service stops release driver outputs cleanly.
Changes:
- Adds a persistent SIGTERM handler while preserving Ctrl+C force-quit behavior.
- Changes the shared stop flag and platform entry points to
volatile std::sig_atomic_t. - Updates shutdown instructions and corrects entry-point documentation.
| File | Description |
|---|---|
teensy/main.cpp |
Aligns the stop flag and mm_main declaration. |
src/platform/desktop/main_desktop.cpp |
Adds SIGTERM handling, updates the flag, and condenses comments. |
src/main.cpp |
Updates the shared mm_main stop-flag parameter. |
moonwalk/02-install.yaml |
Documents clean shutdown with systemctl stop. |
esp32/main/main.cpp |
Aligns the stop flag and mm_main declaration. |
docs/reference/build-system.md |
Corrects the shared signature and platform initialization descriptions. |
Review effort: Balanced
|
|
||
| // SIGTERM is how systemd, Docker and kill stop a service: the same clean stop, so a HUB75 panel goes dark rather than freezing lit. Not one-shot: a second one would cut the stop short, and a service manager escalates to SIGKILL itself. | ||
| struct sigaction saTerm{}; | ||
| saTerm.sa_handler = [](int) { running = 0; }; |

systemctl stop,docker stopandkillnow stop MoonLight the way Ctrl+C does: every driver releases its output, so a HUB75 panel goes dark rather than freezing lit, and the service stops at once rather than after systemd's 90-second timeout.Core
volatile std::sig_atomic_t, the one type a signal handler may write and the main thread read:mm_main's signature and the flag in main_desktop.cpp, esp32/main/main.cpp and teensy/main.cpp.Docs/CI
mm_main(keepRunning, httpPort)is its signature; the ESP32 entry point initializes NVS, not Ethernet.sudo systemctl stop moonlightstops MoonLight cleanly.Tests
systemctl stopdarkens the panels and returns at once.Reviews
volatile boolas the flag a handler writes: done,sig_atomic_t.signal(SIGTERM)line: done, removed, since Windows never raises SIGTERM.mm_mainsignature: done.What an agent wrote: Claude Code (Opus) wrote the code, the tests and this text from my direction; I reviewed every line and vouch for it.
Tested: On a Raspberry Pi 5 (DietPi):
systemctl stop moonlightnow stops MoonLight at once and darkens a HUB75 wall, where it used to wait out systemd's 90-second timeout. On this branch on macOS, 2848 of 2849 desktop tests pass; the one failure is main's discovery test injecting a WLED from 192.168.1.186, which this Mac holds, the bug #225 fixes. The ESP32-S3 build is clean.check_coderan on this branch before the push.Skipped checks:
mm_mainor the signal handlers.🤖 Generated with Claude Code