HydraIssues

Stream killed every 60s by LAN/WG host flip (stopMoonlight pkills HydraExperienceNet)
closed bug Project: hydraheadflatscreen Reporter: 21 Apr 2026 15:39

Description

Summary

With a head-assignment set, hydraheadflatscreen kills the active stream on macOS roughly every 60 seconds. The agent flips c.currentHost between the body's LAN IP and WireGuard IP on alternating ticks, then detects a "stream target changed" on the next tick and calls stopMoonlight() — which pkill -x HydraExperienceNet's the kiosk and any live stream subprocess.

Observed

5-minute stability test on peppy-dumpling-32 streaming rupelmonde-castle-viewer from boom-pickle-38 (LAN 10.110.0.51 / WG 10.10.100.7). Stream subprocess alive for ~15-30 seconds, then gone; stream status stays streaming in LocalAPI (stale) while the user sees the kiosk grid return. Log pattern repeats every 60s:

routing via LAN: 10.110.0.51
routing via LAN: 10.110.0.51
stream target changed: 10.110.0.51/rupelmonde-castle-viewer -> 10.10.100.7/rupelmonde-castle-viewer
pairing with Sunshine at 10.110.0.51...
launching kiosk: 10.110.0.51

Root cause

pkg/client/client.go:147-211. The change-detection path uses stableHost (WireGuard IP) which is correct, but two fall-through assignments overwrite c.currentHost with the resolved (LAN-preferred) host:

  • Line 203 correctly sets c.currentHost = stableHost after launching.
  • Line 209 (when Moonlight/kiosk is already running) sets c.currentHost = host — the ResolvedHost, which will be the LAN IP when LAN is reachable.

On the next tick host is still LAN but stableHost is WG. stableHost != c.currentHost → "stream target changed" → stopMoonlight() (which runs pkill -x HydraExperienceNet, killing both the kiosk and any stream subprocess).

Secondary issue: stopMoonlight() at pkg/client/moonlight_darwin.go:88-93 is the broad hammer that kills everything named HydraExperienceNet. On a no-op target change (LAN/WG flip), we should not be calling it at all; the fix above prevents that path being entered.

Proposed fix

In pkg/client/client.go:209, change c.currentHost = host to c.currentHost = stableHost. Matches line 203 and the comparison at line 152.

Impact

  • Any head on macOS with a head-assignment where the body is reachable via both LAN and WG — i.e. a properly-configured same-venue kiosk+body pair, which is the happy path — has its stream killed every 60s.
  • Symptom to end users: stream dies after ~30-60s, kiosk grid returns, user must click the tile again, repeat.
  • Discovered while stability-testing Rupelmonde kiosk after shipping the venue-filter fix (hydraheadflatscreen v2.0.24).

Comments (1)

cederik 21 Apr 2026 15:49

Fix shipped: hydraheadflatscreen v2.0.25 (commit 50b9302). Verified on peppy-dumpling-32 streaming rupelmonde-castle-viewer from boom-pickle over LAN: 5-min stability test held the same stream PID (4784) from T+15s through T+303s with zero drops, zero stream-target-changed events, and the experience continued rendering interactive scenes to the end. Runbook updated with the symptom + version gate.