The packaged reticulum-daemon is a PyInstaller one-file binary: the
bootloader extracts a ~48M _MEI* dir into TMPDIR and only deletes it on
clean exit. ReticulumLink's shutdown SIGKILLed the process group
immediately (kill_on_drop + instant SIGTERM+SIGKILL in Drop), so the
cleanup never ran and every reconnect/restart stranded another 48M in
/tmp — filling .116's 12G tmpfs in ~4h.
Two-pronged fix:
- terminate_group(): group-wide SIGTERM now, SIGKILL from a detached
backstop thread 5s later, used on every shutdown path (Drop and all
spawn-failure paths, which previously used bare start_kill and could
orphan the forked Python child too).
- Per-interface private TMPDIR under the runtime dir, wiped on every
(re)spawn — even a hard-killed or power-lost daemon can never
accumulate stale extraction dirs, and they land on the data disk
instead of the small tmpfs /tmp.
Verified: unit tests + the ignored mesh_service_connects_over_
reticulum_tcp_client integration test (spawns two real daemons over
loopback TCP through the changed spawn/terminate path), clean teardown
with no stray processes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>