Commit Graph
35 Commits
Author SHA1 Message Date
Isaac ConnorandClaude Opus 5 1f70965a98 fix: retry deadlocked queries with bounded backoff instead of failing them
zmDbDo, zmDbDoInsert and zmDbDoUpdate all decided what to do with a failed
query by testing for ER_LOCK_WAIT_TIMEOUT alone, which got both halves of
lock contention wrong:

- ER_LOCK_DEADLOCK was not retried at all. InnoDB resolves a deadlock by
  rolling one side back and expects that side to re-run; instead the query
  was logged and abandoned. Event creation goes through zmDbDoInsert, which
  is where this actually bites.

- ER_LOCK_WAIT_TIMEOUT re-ran immediately and forever, with no delay and no
  attempt limit, so two writers deadlocking against each other kept
  colliding on the same schedule.

Both now go through one retry decision: five attempts with a jittered
50ms-doubling backoff, then give up and report. The jitter is what stops
two contending sessions waking together and repeating the deadlock.

The wait happens under db_mutex, which every other database user in the
process is blocked on, so the budget is deliberately small -- about 3.1s
across all five attempts. That is still far less than the unbounded
ER_LOCK_WAIT_TIMEOUT loop it replaces, where each round costs a full
innodb_lock_wait_timeout. The change in behaviour is that a query which
would eventually have won after many minutes is now abandoned; it is
reported at Error with the attempt count.

The error is now logged once, when giving up, rather than on every round.
mysql_errno is read next to mysql_error rather than after the logging
call, so it cannot be clobbered in between.

Two other things, both small and both in the same area:

zmDbEscapeString called mysql_real_escape_string unconditionally, and that
reads the character set off the connection, so a closed handle sends it
into freed state. It now falls back to escaping the injection-relevant
characters itself. That fallback is only correct because the connection is
utf8mb4, where no byte of a multi-byte sequence is ASCII and so no sequence
can absorb a trailing backslash; the comment says so, since it would be
wrong for a character set like GBK. It deliberately does not take
db_mutex to read the flag: the logger calls this from Error(), and
zmDbFetch reaches Error() while holding db_mutex, so locking here would
self-deadlock the process on any failed query.

zm_rtsp_server was the one daemon closing the database without stopping
the queue that writes through it. Fixed at the call site rather than
inside zmDbClose, which holds db_mutex while the queue thread needs that
same mutex to drain -- joining it from in there would deadlock.

Tests: tests/zm_db_contention.cpp covers the retry budget only, 2011
assertions. Verified it fails when the budget is removed. The retry loop
itself needs a database and two contending sessions and is NOT covered;
it wants verifying against a real server under contention before this is
relied on. Full suite 12171 assertions in 133 test cases. Builds clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Y6FieTwEXuLhhR4e2yiax
2026-09-04 07:15:30 -04:00
Isaac ConnorandClaude Opus 4.7 0d93742b97 fix: delete FifoSources before RemoveSession on reconnect failure
When monitor->ShmValid() returns false and the reconnect attempt fails,
the cleanup path erased the video_source/audio_source entries from their
maps without deleting the FifoSource objects, then called RemoveSession
on the MediaSession. Two problems:

1. ZoneMinderFifoSource is only stopped/joined in its destructor. erase()
   on a raw pointer leaks the object and leaves its read_thread_ and
   write_thread_ running.

2. The xop::H264Source / H265Source / AV1Source is owned by the
   MediaSession and gets destroyed inside RemoveSession. The orphaned
   FifoSource still holds a raw m_h264Source pointer set via
   setH264Source(); the next SPS NAL parsed by the still-running
   ReadRun thread calls H264Source::SetSPS on freed memory and crashes
   in std::vector::assign.

Stack of the observed crash:
  H264Source::SetSPS                          H264Source.h:34
  H264_ZoneMinderFifoSource::splitFrames      zm_rtsp_server_fifo_h264_source.cpp:53
  ZoneMinderFifoSource::getNextFrame          zm_rtsp_server_fifo_source.cpp:265
  ZoneMinderFifoSource::ReadRun               zm_rtsp_server_fifo_source.cpp:59

Mirror the correct order already used by the "monitor went away" path
above (lines 188-197) and by the shutdown path (lines 362-375): delete
the FifoSources first so their dtors set stop_ and join the threads,
then RemoveSession can safely destroy the H264Source.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 08:47:13 -04:00
Isaac ConnorandClaude Opus 4.7 509d8b4d3f feat: add G.711 μ-law (PCMU) audio support to zm_rtsp_server
Mirror the existing pcm_alaw branch with a pcm_mulaw branch that
creates an xop::G711USource. Cameras emitting PCMU audio can now
be re-streamed via the built-in RTSP server.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:06:36 -04:00
Isaac Connor d5531180f4 Add av1 support 2026-01-31 12:43:03 -05:00
Isaac ConnorandClaude Opus 4.5 a6e91a4699 feat: add SPS/PPS extraction to RTSP server for correct video dimensions
Extract H264 SPS/PPS and H265 VPS/SPS/PPS from video stream and pass
to xop sources for inclusion in SDP sprop-parameter-sets. This allows
RTSP clients like go2rtc to properly decode video with correct
dimensions.

Also adds auth_hash refresh support to go2rtc manager to prevent
authentication timeout after 2 hours.

Changes:
- zm_rtsp_server_fifo_h264_source.cpp: Re-enable SPS/PPS extraction
- zm_rtsp_server_fifo_video_source.h: Add xop source pointers
- zm_rtsp_server.cpp: Connect FIFO sources to xop sources
- zm_monitor_go2rtc.cpp: Add periodic auth_hash refresh
- zm_monitor.h: Add refresh tracking members to Go2RTCManager
- dep/RtspServer: Update xop H264/H265Source with sprop support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:07:15 -05:00
Isaac Connor 5a0a53f72c Reload db config on reload 2026-01-29 17:30:43 -05:00
Aaron Kling c4683d90a9 Format code using astyle google format
Commands used:
astyle --style=google --indent=spaces=2 --keep-one-line-blocks src/*.cpp
astyle --style=google --indent=spaces=2 --keep-one-line-blocks src/*.h
2024-03-26 13:43:58 -05:00
Isaac Connor ecd2049997 Fix == to - 2023-06-04 07:23:08 -04:00
Isaac Connor 4671949532 Fix inverted Delete logic 2023-06-04 07:18:58 -04:00
Isaac Connor 0ded374bc3 Don't RTSP re-stream deleted monitos 2023-05-31 16:42:16 -04:00
Isaac Connor dfbd9f4ed4 Set the rtsp version so that the mandatory s field in the SDP is filled 2022-09-18 14:16:35 -04:00
Isaac Connor 17df9713b1 Replace Function with Capturing 2022-09-12 11:55:09 -04:00
Isaac Connor 3d5767b326 Merge branch 'master' into multistream 2022-02-01 16:52:42 -05:00
Isaac Connor 4949159b88 Rough in pcm alaw support. Untested. 2022-02-01 14:06:12 -05:00
Isaac Connor df1b42ab53 add setLastViewed for monitors that have clients 2021-10-24 17:45:22 -04:00
Isaac Connor 1ee85caaae Don't crash when unable to create source. erase will call the desctructor. Fixes #3344 2021-09-15 12:56:39 -04:00
Isaac Connor c56025beab Use std::unordered_map instead of std::map for performance. Be slightly more efficicent by storing an interator and using it instead of continually indexing into the std::map. Fix crash when a monitor's mmap file size changes 2021-06-13 14:08:51 -04:00
Peter Keresztes Schmidt 14cb2bc3dd zm_rtsp_server: Remove an unused variable 2021-05-01 00:24:54 +02:00
Isaac Connor 3d11366c0f restart stream when RTSP stream name changes 2021-04-29 06:38:42 -04:00
Isaac Connor f61618b244 rework rtsp_server to look for new and free up old monitors 2021-04-27 16:35:13 -04:00
Isaac Connor d9aac9bea9 it is ok to have empty monitors, should detect when new ones arrive 2021-04-27 10:28:46 -04:00
Isaac Connor c83b9190cb pass peer_ip by const ref 2021-04-20 17:16:09 -04:00
Isaac Connor ff2017d8b0 Initialize video_sources and audio_sources to prevent crash 2021-04-20 09:22:37 -04:00
Isaac Connor 3fc9f5ac32 Prevent multiple threads being created by zmc restart by converting sources into a vector 2021-04-19 12:38:35 -04:00
Peter Keresztes Schmidt b5f3682d4e utils: some more reshuffling/grouping and formatting 2021-04-04 01:18:34 +02:00
Isaac Connor d2efb51b0d rearrange a bit, put back setting width and height on video source even though it isn't used yet. Remove signal blocking stuff that we don't use 2021-03-22 17:49:59 -04:00
Isaac Connor baf73fea7b Ensure that we disconnect when ShmValid fails 2021-03-15 15:11:12 -04:00
Isaac Connor 562e7c7e80 Add authentication 2021-03-10 13:19:41 -05:00
Isaac Connor b1f6eb127b Switch from live555 to PHZ76/RtspServer 2021-03-10 11:01:04 -05:00
Isaac Connor 41085c9e5c Remove final bits of zm_video writer. 2021-03-08 22:14:13 -05:00
Isaac Connor 07339e443b Add RTSP Server shutdown code 2021-03-05 14:13:24 -05:00
Peter Keresztes Schmidt c78e174e78 RTSPServerThread: Convert to std::thread 2021-03-03 23:31:53 +01:00
Isaac Connor b2ff9af238 Add setting of frequency and channels for audio stream 2021-03-01 16:49:27 -05:00
Isaac Connor 7ba6e45505 Rough in rtsp_server concept. Wait for fifo's to exist before connecting. Check for monitor disconnection. WIP 2021-03-01 16:49:27 -05:00
Isaac Connor fdf1fbd497 Add a fifo version of the rtsp server 2021-03-01 16:46:48 -05:00