Commit Graph
3 Commits
Author SHA1 Message Date
nicandClaude Opus 5.5 596fb5ab70 fix: free a stream's monitor and playback buffer when nph-zms exits (#5186)
* fix: free a stream's monitor and playback buffer when nph-zms exits

Every nph-zms exited with ~1 MB still allocated, reported by LeakSanitizer
on every stream:

- The monitor's zones each hold a shared_ptr back to it, so releasing the
  stream's reference never freed the Monitor, its zones (a full-frame zone
  image each), camera or links. zmc breaks the cycle with disconnect() on
  exit; zms never did. ~StreamBase now calls it.
- The buffered-playback SwapImage array (connkey + buffer) was never
  deleted. MonitorStream now frees it in its destructor.

Freed at process exit either way, so nothing grows, but it shows up in
every leak report and hides real ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: check a stream frees its monitor and zones on destruction refs #5186

A stream holds a monitor with one zone; once the stream is destroyed, a
weak_ptr to the monitor must have expired. Each Zone holds a shared_ptr
back to its Monitor, so without ~StreamBase breaking the cycle the monitor,
its zones and their images outlive the stream. Fails on 82901ac1f
(REQUIRE( watched.expired() )), passes with the fix. Needs no database or
sanitizer, so ci-cpp-tests runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: hold the buffered-playback array in a unique_ptr refs #5186

temp_image_buffer is now a std::unique_ptr<SwapImage[]>, so it is freed
with the stream without a hand-written destructor, and the leak cannot
come back by dropping that line. The array is private and only allocated
in runStream(), so a unit test cannot see it freed without a sanitizer;
under LeakSanitizer, buffered nph-zms streams leaked 48,008 bytes from
runStream() on 82901ac1f and nothing with this branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 17:34:09 -04:00
Jash f5cfbcd54c fix: make MonitorStream playback state shared with the command thread atomic fixes #4939 2026-08-16 16:46:47 +05:30
Steve GilvarryandClaude Opus 4.8 dc4cf32a63 fix: guard zms buffer_level against zero buffer count refs #4936
MonitorStream::processCommand computed buffer_level by dividing by
temp_image_buffer_count (and via MOD_ADD modulo) while only guarding on
playback_buffer. processCommand runs on the command_processor thread,
started in runStream before temp_image_buffer_count is assigned from
playback_buffer. In that window temp_image_buffer_count is still 0 while
playback_buffer is already > 0, so a command arriving then divided by
zero and raised SIGFPE, crashing nph-zms.

Extract the percentage math into MonitorStreamBufferLevel which returns 0
when the buffer count is not positive, and add Catch2 coverage for the
zero-count and wrap-around cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 08:21:29 +10:00