From fe72fd83f89cbe8425bcbf062c65d242ab86f10f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Dec 2021 10:04:35 -0500 Subject: [PATCH 01/13] Fix auth not getting realm from auth headers due to them being an array now. Get auth and ip from Path if not set in ControlAddress. --- .../lib/ZoneMinder/Control/AxisV2.pm | 68 ++++++++++++------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm index 64e284278..e50449927 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm @@ -51,11 +51,21 @@ sub open { my $self = shift; $self->loadMonitor(); - if ( $self->{Monitor}->{ControlAddress} !~ /^\w+:\/\// ) { - # Has no scheme at the beginning, so won't parse as a URI - $self->{Monitor}->{ControlAddress} = 'http://'.$self->{Monitor}->{ControlAddress}; - } - $uri = URI->new($self->{Monitor}->{ControlAddress}); + + if ($self->{Monitor}->{ControlAddress} and ($self->{Monitor}->{ControlAddress} ne 'user:pass@ip')) { + Debug("Getting connection details from Control Address " . $self->{Monitor}->{ControlAddress}); + if ( $self->{Monitor}->{ControlAddress} !~ /^\w+:\/\// ) { + # Has no scheme at the beginning, so won't parse as a URI + $self->{Monitor}->{ControlAddress} = 'http://'.$self->{Monitor}->{ControlAddress}; + } + $uri = URI->new($self->{Monitor}->{ControlAddress}); + } elsif ($self->{Monitor}->{Path}) { + Debug("Getting connection details from Path " . $self->{Monitor}->{Path}); + $uri = URI->new($self->{Monitor}->{Path}); + $uri->scheme('http'); + $uri->port(80); + $uri->path(''); + } use LWP::UserAgent; $self->{ua} = LWP::UserAgent->new; @@ -64,6 +74,7 @@ sub open { $self->{state} = 'closed'; my ( $username, $password, $host ) = ( $uri->authority() =~ /^([^:]+):([^@]*)@(.+)$/ ); + Debug("Have username: $username password: $password host: $host from authority:" . $uri->authority()); $uri->userinfo(undef); @@ -75,40 +86,47 @@ sub open { # test auth my $res = $self->{ua}->get($uri->canonical().$url); - if ( $res->is_success ) { - if ( $res->content() ne "Properties.PTZ.PTZ=yes\n" ) { + if ($res->is_success) { + if ($res->content() ne "Properties.PTZ.PTZ=yes\n") { Warning('Response suggests that camera doesn\'t support PTZ. Content:('.$res->content().')'); } $self->{state} = 'open'; return; } + if ($res->status_line() eq '404 Not Found') { + #older style + $url = 'axis-cgi/com/ptz.cgi'; + $res = $self->{ua}->get($uri->canonical().$url); + Debug("Result from getting ".$uri->canonical().$url . ':' . $res->status_line()); + } - if ( $res->status_line() eq '401 Unauthorized' ) { - + if ($res->status_line() eq '401 Unauthorized') { my $headers = $res->headers(); foreach my $k ( keys %$headers ) { Debug("Initial Header $k => $$headers{$k}"); } if ( $$headers{'www-authenticate'} ) { - my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/; - if ( $tokens =~ /\w+="([^"]+)"/i ) { - if ( $realm ne $1 ) { - $realm = $1; - $self->{ua}->credentials($uri->host_port(), $realm, $username, $password); - $res = $self->{ua}->get($uri->canonical().$url); - if ( $res->is_success() ) { - Info("Auth succeeded after setting realm to $realm. You can set this value in the Control Device field to speed up connections and remove these log entries."); - $self->{state} = 'open'; - return; + foreach my $auth_header ( ref $$headers{'www-authenticate'} eq 'ARRAY' ? @{$$headers{'www-authenticate'}} : ($$headers{'www-authenticate'})) { + my ( $auth, $tokens ) = $auth_header =~ /^(\w+)\s+(.*)$/; + if ( $tokens =~ /\w+="([^"]+)"/i ) { + if ( $realm ne $1 ) { + $realm = $1; + $self->{ua}->credentials($uri->host_port(), $realm, $username, $password); + $res = $self->{ua}->get($uri->canonical().$url); + if ( $res->is_success() ) { + Info("Auth succeeded after setting realm to $realm. You can set this value in the Control Device field to speed up connections and remove these log entries."); + $self->{state} = 'open'; + return; + } + Error('Authentication still failed after updating REALM status: '.$res->status_line); + } else { + Error('Authentication failed, not a REALM problem'); } - Error('Authentication still failed after updating REALM status: '.$res->status_line); } else { - Error('Authentication failed, not a REALM problem'); - } - } else { - Error('Failed to match realm in tokens'); - } # end if + Error('Failed to match realm in tokens'); + } # end if + } # end foreach auth header } else { Debug('No headers line'); } # end if headers From cca79538564ace7753bd3bdc2e0cf6de9f3d148f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Dec 2021 12:26:26 -0500 Subject: [PATCH 02/13] include user and function error message about insufficient permissions. Will make it easier to figure out who tried what. --- src/zmu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zmu.cpp b/src/zmu.cpp index ec4ae7b86..ba96d71be 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -482,7 +482,7 @@ int main(int argc, char *argv[]) { exit_zmu(-1); } if ( !ValidateAccess(user, mon_id, function) ) { - Error("Insufficient privileges for requested action"); + Error("Insufficient privileges for user %s for requested function %x", username, function); exit_zmu(-1); } } // end if auth From 4fa804e9a28f95e534d2e076547a35d053f375d7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Dec 2021 13:33:00 -0500 Subject: [PATCH 03/13] Can only SKIP LOCKED if locking rows. Remove FOR SHARE as it isn't supported on < mysql 8 --- scripts/ZoneMinder/lib/ZoneMinder/Filter.pm | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm index 7b3efad46..f483e545c 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm @@ -413,12 +413,10 @@ sub Sql { $sql .= ' LIMIT 0,'.$filter_expr->{limit}; } if ($$self{LockRows}) { - $sql .= ' FOR UPDATE OF E' - } else { - $sql .= ' FOR SHARE OF E' - } - if ($filter_expr->{skip_locked}) { - $sql .= ' SKIP LOCKED'; + $sql .= ' FOR UPDATE' + if ($filter_expr->{skip_locked}) { + $sql .= ' SKIP LOCKED'; + } } $self->{Sql} = $sql; } # end if has Sql From f6d0274f745f87214a7348adda813ad9796a7d34 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Dec 2021 17:05:56 -0500 Subject: [PATCH 04/13] Fix PrevCycle because monIdx was empty. --- web/skins/classic/views/js/watch.js | 5 ++++- web/skins/classic/views/js/watch.js.php | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 8a0f527c9..90c73dd9f 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -904,9 +904,10 @@ function initPage() { if (monitorType != 'WebSite') { if (streamMode == 'single') { - statusCmdTimer = setTimeout(statusCmdQuery, (Math.random()+0.1)*statusRefreshTimeout); + statusCmdTimer = setTimeout(statusCmdQuery, 100); setInterval(watchdogCheck, statusRefreshTimeout*2, 'status'); } else { + streamCmdTimer = setTimeout(streamCmdQuery, 100); setInterval(watchdogCheck, statusRefreshTimeout*2, 'stream'); } @@ -1054,9 +1055,11 @@ function cycleNext() { } function cyclePrev() { + console.log(monIdx); monIdx --; if (monIdx < 0) { monIdx = monitorData.length - 1; + console.log(monIdx); } if (!monitorData[monIdx]) { console.log('No monitorData for ' + monIdx); diff --git a/web/skins/classic/views/js/watch.js.php b/web/skins/classic/views/js/watch.js.php index ab09d6ca5..d7b108b6d 100644 --- a/web/skins/classic/views/js/watch.js.php +++ b/web/skins/classic/views/js/watch.js.php @@ -1,5 +1,5 @@ Refresh() ?>'; var monitorStreamReplayBuffer = StreamReplayBuffer() ?>; var monitorControllable = Controllable()?'true':'false' ?>; -var monIdx = ''; +var monIdx = ; var nextMid = ""; var mode = ""; From 61fe35a32a0df63673cda7932f48794c5eedeeef Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Dec 2021 14:06:48 -0500 Subject: [PATCH 05/13] Don't log errors when querying a monitor in NONE Function. Just report a 0 status.Fixes #3397 --- src/zmu.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/zmu.cpp b/src/zmu.cpp index ba96d71be..b85227fc4 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -497,6 +497,16 @@ int main(int argc, char *argv[]) { if ( verbose ) { printf("Monitor %u(%s)\n", monitor->Id(), monitor->Name()); } + + if (monitor->GetFunction() == Monitor::NONE) { + if (verbose) { + printf("Current state: None\n"); + } else { + printf("%d", Monitor::UNKNOWN); + } + exit_zmu(-1); + } + if ( !monitor->connect() ) { Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name()); exit_zmu(-1); From e8edeab641e97d213b95526183d1b61edd0dab69 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Dec 2021 14:22:11 -0500 Subject: [PATCH 06/13] parseInt prevEventId and nextEventID to be sure that our tests for != 0 work. Also don't go to previous event if prevEventId ==0.Maybe Fixes #3390 --- web/skins/classic/views/js/event.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index b252c292c..04bf66b7e 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -446,8 +446,10 @@ function streamFastRev(action) { function streamPrev(action) { if (action) { $j(".vjsMessage").remove(); - location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery); - return; + if (prevEventId != 0) { + location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery); + return; + } /* Ideally I'd like to get back to this style if ( vid && PrevEventDefVideoPath.indexOf("view_video") > 0 ) { @@ -619,8 +621,8 @@ function getNearEventsResponse(respObj, respText) { if (checkStreamForErrors('getNearEventsResponse', respObj)) { return; } - prevEventId = respObj.nearevents.PrevEventId; - nextEventId = respObj.nearevents.NextEventId; + prevEventId = parseInt(respObj.nearevents.PrevEventId); + nextEventId = parseInt(respObj.nearevents.NextEventId); prevEventStartTime = Date.parse(respObj.nearevents.PrevEventStartTime); nextEventStartTime = Date.parse(respObj.nearevents.NextEventStartTime); PrevEventDefVideoPath = respObj.nearevents.PrevEventDefVideoPath; From f683557b0eb54eefb4bdf278d07a4c29d46a660b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 14 Dec 2021 15:05:21 -0500 Subject: [PATCH 07/13] Fix Monitor::Control to handle local cameras --- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm index 5646fb897..87b75ad02 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm @@ -241,20 +241,26 @@ sub control { my $command = shift; my $process = shift; - if ( $command eq 'stop' or $command eq 'restart' ) { - if ( $process ) { - `/usr/bin/zmdc.pl stop $process -m $$monitor{Id}`; + if ($command eq 'stop' or $command eq 'restart') { + if ($process) { + runCommand("zmdc.pl stop $process -m $$monitor{Id}"); } else { - `/usr/bin/zmdc.pl stop zma -m $$monitor{Id}`; - `/usr/bin/zmdc.pl stop zmc -m $$monitor{Id}`; + if ($monitor->{Type} eq 'Local') { + runCommand('zmdc.pl stop zmc -d '.$monitor->{Device}); + } else { + runCommand('zmdc.pl stop zmc -m '.$monitor->{Id}); + } } } if ( $command eq 'start' or $command eq 'restart' ) { if ( $process ) { - `/usr/bin/zmdc.pl start $process -m $$monitor{Id}`; + runCommand("zmdc.pl start $process -m $$monitor{Id}"); } else { - `/usr/bin/zmdc.pl start zmc -m $$monitor{Id}`; - `/usr/bin/zmdc.pl start zma -m $$monitor{Id}`; + if ($monitor->{Type} eq 'Local') { + runCommand('zmdc.pl stop zmc -d '.$monitor->{Device}); + } else { + runCommand('zmdc.pl stop zmc -m '.$monitor->{Id}); + } } # end if } } # end sub control From 28d5614da0aa8b83b8e2a1d2c4839c249c8da94c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Dec 2021 09:08:25 -0500 Subject: [PATCH 08/13] Fix missing ; --- scripts/ZoneMinder/lib/ZoneMinder/Filter.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm index f483e545c..726685a7e 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm @@ -413,7 +413,7 @@ sub Sql { $sql .= ' LIMIT 0,'.$filter_expr->{limit}; } if ($$self{LockRows}) { - $sql .= ' FOR UPDATE' + $sql .= ' FOR UPDATE'; if ($filter_expr->{skip_locked}) { $sql .= ' SKIP LOCKED'; } From fe0e4627efc4175d4f16c53d4d668ba740e85483 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Dec 2021 09:08:54 -0500 Subject: [PATCH 09/13] Specify ZoneMinder::General for runCommand --- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm index 87b75ad02..d179534d4 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm @@ -243,23 +243,23 @@ sub control { if ($command eq 'stop' or $command eq 'restart') { if ($process) { - runCommand("zmdc.pl stop $process -m $$monitor{Id}"); + ZoneMinder::General::runCommand("zmdc.pl stop $process -m $$monitor{Id}"); } else { if ($monitor->{Type} eq 'Local') { - runCommand('zmdc.pl stop zmc -d '.$monitor->{Device}); + ZoneMinder::General::runCommand('zmdc.pl stop zmc -d '.$monitor->{Device}); } else { - runCommand('zmdc.pl stop zmc -m '.$monitor->{Id}); + ZoneMinder::General::runCommand('zmdc.pl stop zmc -m '.$monitor->{Id}); } } } if ( $command eq 'start' or $command eq 'restart' ) { if ( $process ) { - runCommand("zmdc.pl start $process -m $$monitor{Id}"); + ZoneMinder::General::runCommand("zmdc.pl start $process -m $$monitor{Id}"); } else { if ($monitor->{Type} eq 'Local') { - runCommand('zmdc.pl stop zmc -d '.$monitor->{Device}); + ZoneMinder::General::runCommand('zmdc.pl start zmc -d '.$monitor->{Device}); } else { - runCommand('zmdc.pl stop zmc -m '.$monitor->{Id}); + ZoneMinder::General::runCommand('zmdc.pl start zmc -m '.$monitor->{Id}); } } # end if } From 12ebdacf543d506d687b9b779c94ea2e19381dce Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Dec 2021 09:09:14 -0500 Subject: [PATCH 10/13] specify ZoneMinder::Database for zmSQLExecute --- scripts/zmfilter.pl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index fd927020f..c0cdf7235 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -1048,7 +1048,7 @@ sub executeCommand { Error("Command '$command' exited with status: $status"); return 0; } else { - zmSQLExecute('UPDATE `Events` SET `Executed` = 1 WHERE `Id` = ?', $Event->{Id}); + ZoneMinder::Database::zmSQLExecute('UPDATE `Events` SET `Executed` = 1 WHERE `Id` = ?', $Event->{Id}); } return 1; } From d86456b6f2e13a64b2dbc6cb045f41904451addd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Dec 2021 09:11:08 -0500 Subject: [PATCH 11/13] revamp, using ZoneMinder::Monitor methods to reduce code. Reduce last analysze time was zero to a debug. Fixes #3389 --- scripts/zmwatch.pl.in | 136 +++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 81 deletions(-) diff --git a/scripts/zmwatch.pl.in b/scripts/zmwatch.pl.in index 96235ccd3..1b4790bce 100644 --- a/scripts/zmwatch.pl.in +++ b/scripts/zmwatch.pl.in @@ -56,6 +56,7 @@ use constant START_DELAY => 30; # To give everything else time to start @EXTRA_PERL_LIB@ use ZoneMinder; use ZoneMinder::Storage; +use ZoneMinder::Monitor; use POSIX; use DBI; use autouse 'Data::Dumper'=>qw(Dumper); @@ -80,91 +81,75 @@ Info('Watchdog starting, pausing for '.START_DELAY.' seconds'); sleep(START_DELAY); my $dbh = zmDbConnect(); -my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors'; -my $sth = $dbh->prepare_cached($sql) - or Fatal("Can't prepare '$sql': ".$dbh->errstr()); while (!$zm_terminate) { - while ( ! ( $dbh and $dbh->ping() ) ) { - if ( ! ( $dbh = zmDbConnect() ) ) { + while (!($dbh and $dbh->ping())) { + if (!($dbh = zmDbConnect())) { sleep($Config{ZM_WATCH_CHECK_INTERVAL}); } } - my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) - or Fatal('Can\'t execute: '.$sth->errstr()); - while( my $monitor = $sth->fetchrow_hashref() ) { + foreach my $monitor (ZoneMinder::Monitor->find($Config{ZM_SERVER_ID} ? (ServerId=>$Config{ZM_SERVER_ID}) : ())) { next if $monitor->{Function} eq 'None'; next if $monitor->{Type} eq 'WebSite'; my $now = time(); my $restart = 0; - if (zmMemVerify($monitor)) { -# Check we have got an image recently - my $capture_time = zmGetLastWriteTime($monitor); - if (!defined($capture_time)) { -# Can't read from shared data - Debug('LastWriteTime is not defined.'); - zmMemInvalidate($monitor); - next; - } - Debug("Monitor $$monitor{Id} LastWriteTime is $capture_time."); - if (!$capture_time) { - my $startup_time = zmGetStartupTime($monitor); - if (($now - $startup_time) > $Config{ZM_WATCH_MAX_DELAY}) { - Warning( - "Restarting capture daemon for $$monitor{Name}, no image since startup. ". - "Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}" - ); - $restart = 1; - } else { - # We can't get the last capture time so can't be sure it's died, it might just be starting up. - zmMemInvalidate($monitor); - next; - } - } - if (!$restart) { - my $max_image_delay = ( - $monitor->{MaxFPS} - &&($monitor->{MaxFPS}>0) - &&($monitor->{MaxFPS}<1) - ) ? (3/$monitor->{MaxFPS}) - : $Config{ZM_WATCH_MAX_DELAY} - ; - my $image_delay = $now - $capture_time; - Debug("Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay"); - if ( $image_delay > $max_image_delay ) { - Warning("Restarting capture daemon for " - .$monitor->{Name}.", time since last capture $image_delay seconds ($now-$capture_time)" - ); - $restart = 1; - } - } # end if ! restart - } else { + + zmMemInvalidate($monitor); + if (!zmMemVerify($monitor)) { Info("Restarting capture daemon for $monitor->{Name}, shared data not valid"); - $restart = 1; + $monitor->control('restart'); + next; } - if ($restart) { - my $command; - if ($monitor->{Type} eq 'Local') { - $command = 'zmdc.pl restart zmc -d '.$monitor->{Device}; - } else { - $command = 'zmdc.pl restart zmc -m '.$monitor->{Id}; + # Check we have got an image recently + my $capture_time = zmGetLastWriteTime($monitor); + if (!defined($capture_time)) { + # Can't read from shared data + Warning('LastWriteTime is not defined.'); + next; + } + Debug("Monitor $$monitor{Id} LastWriteTime is $capture_time."); + if (!$capture_time) { + # We can't get the last capture time so can't be sure it's died, it might just be starting up. + my $startup_time = zmGetStartupTime($monitor); + if (($now - $startup_time) > $Config{ZM_WATCH_MAX_DELAY}) { + Warning( + "Restarting capture daemon for $$monitor{Name}, no image since startup. ". + "Startup time was $startup_time - now $now > $Config{ZM_WATCH_MAX_DELAY}" + ); + $monitor->control('restart'); } - runCommand($command); - } elsif ($monitor->{Function} ne 'Monitor') { -# Now check analysis daemon - $restart = 0; + next; + } + + my $max_image_delay = ( + $monitor->{MaxFPS} + &&($monitor->{MaxFPS}>0) + &&($monitor->{MaxFPS}<1) + ) ? (3/$monitor->{MaxFPS}) + : $Config{ZM_WATCH_MAX_DELAY} + ; + my $image_delay = $now - $capture_time; + Debug("Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay"); + if ($image_delay > $max_image_delay) { + Warning('Restarting capture daemon for '.$monitor->{Name}. + ", time since last capture $image_delay seconds ($now-$capture_time)"); + $monitor->control('restart'); + next; + } + + if ($monitor->{Function} ne 'Monitor') { + # Now check analysis thread # Check we have got an image recently my $image_time = zmGetLastReadTime($monitor); if (!defined($image_time)) { -# Can't read from shared data - $restart = 1; + # Can't read from shared data Error("Error reading shared data for $$monitor{Id} $$monitor{Name}"); + $monitor->control('restart'); + next; } elsif (!$image_time) { -# We can't get the last capture time so can't be sure it's died. - #$restart = 1; - Error("Last analyse time for $$monitor{Id} $$monitor{Name} was zero."); + Debug("Last analyse time for $$monitor{Id} $$monitor{Name} was zero."); } else { my $max_image_delay = ( $monitor->{MaxFPS} &&($monitor->{MaxFPS}>0) @@ -176,25 +161,14 @@ while (!$zm_terminate) { Debug("Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay"); if ($image_delay > $max_image_delay) { Warning("Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting," - ." time since last analysis $image_delay seconds ($now-$image_time)" - ); - $restart = 1; + ." time since last analysis $image_delay seconds ($now-$image_time)"); + $monitor->control('restart'); + next; } } - if ($restart) { - Info("Restarting analysis daemon for $$monitor{Id} $$monitor{Name}"); - my $command; - if ( $monitor->{Type} eq 'Local' ) { - $command = 'zmdc.pl restart zmc -d '.$monitor->{Device}; - } else { - $command = 'zmdc.pl restart zmc -m '.$monitor->{Id}; - } - runCommand($command); - } # end if restart } # end if check analysis daemon - # Prevent open handles building up if we have connect to shared memory - zmMemInvalidate($monitor); # Close our file handle to the zmc process we are about to end + } # end foreach monitor sleep($Config{ZM_WATCH_CHECK_INTERVAL}); From 854d11ce9d44fb6752a5ded12976cec8e3b706d6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Dec 2021 09:11:46 -0500 Subject: [PATCH 12/13] List the connkey that isn't open, differentiate logs a bit to help debug. --- src/zm_stream.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index 5255d3ab2..88ccd11d1 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -128,10 +128,10 @@ bool StreamBase::checkCommandQueue() { return true; } } else if ( connkey ) { - Warning("No sd in checkCommandQueue, comms not open?"); + Warning("No sd in checkCommandQueue, comms not open for connkey %06d?", connkey); } else { // Perfectly valid if only getting a snapshot - Debug(1, "No sd in checkCommandQueue, comms not open?"); + Debug(1, "No sd in checkCommandQueue, comms not open."); } return false; } // end bool StreamBase::checkCommandQueue() @@ -387,8 +387,8 @@ void StreamBase::openComms() { rem_addr.sun_family = AF_UNIX; last_comm_update = std::chrono::system_clock::now(); + Debug(3, "comms open at %s", loc_sock_path); } // end if connKey > 0 - Debug(3, "comms open at %s", loc_sock_path); } // end void StreamBase::openComms() void StreamBase::closeComms() { From f1db88510eab5a6cd0213c87531d2fadaf4b6ef0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Dec 2021 09:23:21 -0500 Subject: [PATCH 13/13] remove debug, fix eslint --- web/skins/classic/views/js/watch.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 90c73dd9f..f290e1998 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1055,11 +1055,9 @@ function cycleNext() { } function cyclePrev() { - console.log(monIdx); monIdx --; if (monIdx < 0) { monIdx = monitorData.length - 1; - console.log(monIdx); } if (!monitorData[monIdx]) { console.log('No monitorData for ' + monIdx);