When CMD_STOP is sent via AJAX using ZMS MJPEG streaming, the response
was incorrectly returning paused=true instead of indicating a stopped
state (paused=false).
Changes:
- Add `stopped` boolean to StreamBase (zm_stream.h)
- MonitorStream: CMD_STOP now sets stopped=true, paused=false instead
of paused=true; run loop skips frame sending when stopped
- EventStream: CMD_STOP sets stopped=true (was already setting
paused=false); run loop skips frame sending when stopped
- All other play/pause commands reset stopped=false
- Both streams include stopped field in the status response struct
- stream.php unpacks the new stopped field from MSG_DATA_WATCH and
MSG_DATA_EVENT responses
- MonitorStream.js handles stopped status in UI (shows 'Stopped' mode)
- EventStream.js tracks stopped state from server response
Fixes issue: CMD_STOP response paused=true should be paused=false
Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/ba9cb47a-a3e8-4e13-aec7-c9cd258e2a3d
Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
When setStreamStart()->loadMonitor() failed (e.g. monitor id not found,
shm not yet mapped), zms continued into runStream() for non-SINGLE
stream types and dereferenced a null Monitor shared_ptr at
monitor->GetFPS(), crashing in get_capture_fps with fault address 0x618.
Bail early after the STREAM_SINGLE branch with a "Not connected" text
frame, mirroring the SINGLE-type recovery. For STREAM_JPEG, emit the
multipart Content-Type first so sendTextFrame produces a well-formed
response. Placed before openComms()/command_processor spawn so there
is no resource teardown to do on the bail path.
When a browser closes a streaming connection, fwrite to stdout raises
SIGPIPE. Without a handler the default action terminates the process
immediately, skipping exit_zm() and leaving the DB handle and log
unclosed.
Add zm_pipe_handler that sets zm_terminate so zms falls out of its
streaming loop and exits through the normal shutdown path. Clarify
the sendFrame comment to match.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a boolean analysis_image field to the CMD_QUERY status response that
reports whether zms is actually sending analysis images (with motion zone
overlays) or regular capture images. This lets MonitorStream.js detect
when the stream state is out of sync with what the client requested and
re-send the CMD_ANALYZE_ON/OFF command to correct it.
The field is true only when frame_type is FRAME_ANALYSIS, shared memory
is valid, and the monitor has analysis enabled — matching the same
condition used to select the image in the streaming loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The command processor thread could crash dereferencing monitor->shared_data
or monitor->trigger_data while the main thread was in loadMonitor() calling
disconnect() which munmaps shared memory and nulls those pointers.
Three fixes:
- Guard against null monitor at the top of processCommand
- Add monitor_mutex to StreamBase, held during disconnect/connect in
loadMonitor and during shared memory reads in processCommand, so the
command thread cannot access shared memory while it is being remapped
- Initialize status_data.analysing and status_data.score in the
!ShmValid branch where they were previously sent uninitialized
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SharedData field and methods to track when analysis images are being
viewed, mirroring the existing last_viewed_time functionality. This allows
the analysis process to know if someone is actively viewing analysis images.
- Add last_analysis_viewed_time to SharedData struct
- Add getLastAnalysisViewed(), setLastAnalysisViewed(), hasAnalysisViewers()
- Update MonitorStream to set flag when streaming FRAME_ANALYSIS
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>