Repository navigation
Conversation
Monitor::Reload() (the RELOAD action `zmu -m N -L` sends) re-reads the monitor row, which replaces linked_monitors_string, but the MonitorLinkExpression built from it is only rebuilt in connect(). The old links stayed in use until zmc reconnected: after changing LinkedMonitors from 3 to 4 and reloading, zmc kept scoring monitor 3 and ignored alarms on 4. Rebuild the expression in Reload(), under event_mutex, which Analyse() holds while it evaluates linked_monitors. fixes ZoneMinder#5275 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Impact: fix-medium (after zmu -L, a changed LinkedMonitors is ignored until the next reconnect)
TL;DR
zmu -m N -L, zmc keeps linking to the old LinkedMonitors until it reconnects.Monitor::Reload()callsReloadLinkedMonitors()after re-reading the row, underevent_mutex; 1 file, +9/-0Reload()runs on zmc's main thread while the analysis thread evaluateslinked_monitors;Analyse()holdsevent_mutexfor that whole section (zm_monitor.cpp:2120-2694), so the swap takes the same lock. Rebuilding queries the database once per linked monitor while holding it.Details: reproduction, change, checks
Before
Upstream master
233a15828, clean build. Monitor 2 linked to 3, then LinkedMonitors set to 4and
zmu -m 2 -L; monitors 4 and 3 force-alarmed in turn:(hikvision-1 is monitor 3.)
Reload()replaceslinked_monitors_stringthroughLoad()butthe parsed expression is only rebuilt in
connect().Change
src/zm_monitor.cpp(Monitor::Reload): callReloadLinkedMonitors()afterLoad(), insidea
std::lock_guardonevent_mutex, whichAnalyse()holds while it readslinked_monitors.The SIGHUP path (
zmc.cpp:449-455) also callsReload(), afterdisconnect(); there theexpression is built once more and replaced again by
connect(), which costs one query perlinked monitor and changes nothing else.
Reload()needs a monitor row and shared memory; the reload is covered by thelive probe above.
Behaviour changes
zmu -Linstead of on the next reconnectzmu -Lwith linked monitorsReloadLinkedMonitorsevent_mutexwhile the expression is rebuiltSide fixes in this PR: none.
Relation to #5272 (B81): independent and merges cleanly. On master, between
Load()replacingthe string and this rebuild, the old tokens still view the replaced string; #5272 gives the
expression its own copy, which closes that window. With both, the old expression is never read
after its string changes.
After
Branch
fix/b84-reload-linked-monitorsata5892c71e(base233a15828):-DENABLE_WERROR=ON(gcc, Debian trixie)check --quick(one run on a throwaway branch,31b577409, merging this with the two other fixes from the same lab session: bad LinkedMonitors tokens, and the zms zoom crop)Not run: macOS clang build; TSan/ASan runs of the reload. Backport to release-1.38: same bug and
same locking in
Analyse(); the cherry-pick conflicts only on context (master'sLoadActions()call in
Reload()), the same block goes afterLoad().Tested as
bce169449;a5892c71eis the same tree withfixes #5275added to the message.fixes #5275
🤖 Generated with Claude Code