Exercised code paths echo diagnostics (dropOrphans() dropped-viewer lines,
GeoLite2 "[ERROR]" messages, ModuleLoader/GitHubReleases error_log output)
that clutter PHPUnit output without any test asserting on them:
- FanoutSyncOrphanTest / GeoLiteReleaseUpdaterTest: wrap each test in
ob_start()/ob_end_clean() via setUp()/tearDown().
- tests/bootstrap.php: route error_log() to /dev/null.
No production behaviour changes.
A daemon-served TS viewer's row is written with pid 0 — the PHP worker that
admitted it returns at the X-Accel hand-off. closeConnection() only killed
a pid above 0 and then deleted the row, so a limit eviction or an admin
kick left the viewer streaming from the daemon, untracked: a line limited
to one connection could hold any number of TS streams.
- FanoutClient::dropConnection() calls the daemon's new
DELETE /connections/<uuid> (XC_VM_Fanout, feature "drop_connection").
- ConnectionTracker::dropDaemonViewer() drops a pid-0 viewer directly, or
sends a drop_con signal to the viewer's node (DB and Redis signal paths,
handled by SignalsCommand). Both closeConnection() implementations use it.
- The limiter spares the requesting connection by uuid: every daemon row
shares pid 0, so the old "not my pid" check let a new viewer evict
itself. HMAC identities in Redis mode are looked up under their
"<hmac>_<identifier>" key (a null line id hit an int-typed parameter).
- A kicked local HLS viewer loses its segment marker at once, and in Redis
mode a closed HLS connection is no longer silently reopened by the next
playlist request (the MySQL path already required hls_end = 0). A
re-auth that reuses the player's deterministic HLS uuid leaves ENDED /
replaces the closed row, so the reaper cannot delete the new connection.
- fanout_sync also reconciles the other way: a daemon viewer whose row is
gone past a 20 s grace is dropped. It is skipped when the rows could not
be read, so a Redis/DB blip cannot disconnect everyone.
- Redis signal keys include the payload, so pid-less signals do not
overwrite each other.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>