From ed46a6b6ac73a4838f1fe111018ca064cc0faccd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Dec 2016 09:27:54 -0500 Subject: [PATCH 1/6] must call zmMemInvalidate before next --- scripts/zmwatch.pl.in | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/zmwatch.pl.in b/scripts/zmwatch.pl.in index c35c4ea8a..25ecb92f0 100644 --- a/scripts/zmwatch.pl.in +++ b/scripts/zmwatch.pl.in @@ -87,10 +87,6 @@ while( 1 ) { next if $monitor->{Function} eq 'None'; my $restart = 0; - # Prevent open handles building up if we have connect to shared memory - # Many of our error checks below do a next without closing the mem handle. - # zmMemInvalidate will just return of nothing is open, so we can just do this here. - zmMemInvalidate( $monitor ); if ( zmMemVerify( $monitor ) && zmMemRead( $monitor, "shared_data:valid" ) ) @@ -100,11 +96,13 @@ while( 1 ) if ( !defined($image_time) ) { # Can't read from shared data Debug( "LastWriteTime is not defined." ); + zmMemInvalidate( $monitor ); next; } if ( !$image_time ) { # We can't get the last capture time so can't be sure it's died. Debug( "LastWriteTime is = $image_time." ); + zmMemInvalidate( $monitor ); next; } From d2ff6701f4070bde9939745f8b5b42aa1ad89946 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Jan 2017 13:53:02 -0500 Subject: [PATCH 2/6] test --- scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in | 3 +++ scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm | 2 ++ scripts/zmtrigger.pl.in | 11 ++++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in index 286d83db1..ad43a20d1 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -246,10 +246,12 @@ sub zmMemInit { sub zmMemVerify { my $monitor = shift; if ( !zmMemAttach( $monitor, $mem_size ) ) { +print "no attach for $$monitor{Id} $mem_size\n"; return( undef ); } my $mem_key = zmMemKey( $monitor ); +print "mem_key for $$monitor{Id} $mem_key\n"; if ( !defined($mem_verified->{$mem_key}) ) { my $sd_size = zmMemRead( $monitor, "shared_data:size", 1 ); if ( $sd_size != $mem_data->{shared_data}->{size} ) { @@ -365,6 +367,7 @@ sub zmMemRead { sub zmMemInvalidate { my $monitor = shift; my $mem_key = zmMemKey($monitor); +print "zmMemInvalidate $$monitor{Id} $mem_key\n"; if ( $mem_key ) { delete $mem_verified->{$mem_key}; zmMemDetach( $monitor ); diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm index e41019647..3625270a6 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm @@ -120,6 +120,8 @@ sub zmMemAttach $monitor->{MMapHandle} = \*MMAP; $monitor->{MMapAddr} = $mmap_addr; $monitor->{MMap} = \$mmap; + } else { +print "$$monitor{Id} already defined at $$monitor{MMapAddr}\n"; } return( !undef ); } diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 3fc5f43e9..26c091976 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -117,7 +117,7 @@ use bytes; # ========================================================================== use constant MAX_CONNECT_DELAY => 10; -use constant MONITOR_RELOAD_INTERVAL => 300; +use constant MONITOR_RELOAD_INTERVAL => 30; use constant SELECT_TIMEOUT => 0.25; # ========================================================================== @@ -320,7 +320,7 @@ while( 1 ) ] ); - #print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); + print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); #print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); if ( $state == STATE_ALARM || $state == STATE_ALERT @@ -415,8 +415,10 @@ while( 1 ) # If necessary reload monitors if ( (time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL ) { +print "TIme to reload Monitors " . join(',',keys %monitors ). "\n"; foreach my $monitor ( values(%monitors) ) { +print "imvalidating $$monitor{Id}\n"; # Free up any used memory handle zmMemInvalidate( $monitor ); } @@ -443,7 +445,10 @@ sub loadMonitors or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { - next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok + next + if ( !zmMemVerify( $monitor ) ) { +; # Check shared memory ok +} if ( defined($monitors{$monitor->{Id}}->{LastState}) ) { From a66e9e45a228433ab988e46f4c796a60700833e5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Jan 2017 14:22:42 -0500 Subject: [PATCH 3/6] merge a fix from storageareas that adds a test for the shared data being valid and reloads the monitors if it can't reconnect --- scripts/zmtrigger.pl.in | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 3fc5f43e9..887b7a369 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -198,6 +198,7 @@ my %spawned_connections; my %monitors; my $monitor_reload_time = 0; +my $needsReload = 0; $! = undef; my $rin = ''; @@ -313,6 +314,19 @@ while( 1 ) my @out_messages; foreach my $monitor ( values(%monitors) ) { + my $memVerified = 1; + if ( !zmMemRead($monitor, "shared_data:valid") ) { + # Shared data is invalid, attempt to reconnect + zmMemInvalidate($monitor); + $memVerified = zmMemVerify($monitor); + } + + if ( ! $memVerified ) { + # Our attempt to verify the memory handle failed. We should reload the monitors. + $needsReload = 1; + next; + } + my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state", @@ -413,7 +427,7 @@ while( 1 ) } # If necessary reload monitors - if ( (time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL ) + if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )) { foreach my $monitor ( values(%monitors) ) { @@ -421,6 +435,7 @@ while( 1 ) zmMemInvalidate( $monitor ); } loadMonitors(); + $needsReload = 0; } } Info( "Trigger daemon exiting\n" ); From faeb7859618af7cc59da3198fb71cb8677028b4b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Jan 2017 15:08:23 -0500 Subject: [PATCH 4/6] zmMemVerify attaches, so we need to zmMemInvalidate even if the shared data is no good --- scripts/zmx10.pl.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/zmx10.pl.in b/scripts/zmx10.pl.in index 58064a89f..fab30c9af 100644 --- a/scripts/zmx10.pl.in +++ b/scripts/zmx10.pl.in @@ -474,7 +474,11 @@ sub loadTasks or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { - next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok +# Check shared memory ok + if ( !zmMemVerify( $monitor ) ) { + zmMemInvalidate( $monitor ); + next ; + } $monitor_hash{$monitor->{Id}} = $monitor; From a146d7bee12300e3805f93afe0ce30508b68a9e9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Jan 2017 15:08:49 -0500 Subject: [PATCH 5/6] add a test for valid in the shared data. zmc sets this to false when it closes properly --- scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in index ad43a20d1..e72be1c01 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -246,12 +246,10 @@ sub zmMemInit { sub zmMemVerify { my $monitor = shift; if ( !zmMemAttach( $monitor, $mem_size ) ) { -print "no attach for $$monitor{Id} $mem_size\n"; return( undef ); } my $mem_key = zmMemKey( $monitor ); -print "mem_key for $$monitor{Id} $mem_key\n"; if ( !defined($mem_verified->{$mem_key}) ) { my $sd_size = zmMemRead( $monitor, "shared_data:size", 1 ); if ( $sd_size != $mem_data->{shared_data}->{size} ) { @@ -294,6 +292,13 @@ print "mem_key for $$monitor{Id} $mem_key\n"; } return( undef ); } + if ( !zmMemRead($monitor, "shared_data:valid",1) ) { + Error( "Shared data not valid for monitor $$monitor{Id}" ); + return( undef ); + } else { + Debug( "Shared data valid for monitor $$monitor{Id}" ); + } + $mem_verified->{$mem_key} = !undef; } return( !undef ); @@ -367,7 +372,6 @@ sub zmMemRead { sub zmMemInvalidate { my $monitor = shift; my $mem_key = zmMemKey($monitor); -print "zmMemInvalidate $$monitor{Id} $mem_key\n"; if ( $mem_key ) { delete $mem_verified->{$mem_key}; zmMemDetach( $monitor ); From 7ddd5359d05b785d7994e366ea08cf0f5f36b874 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Jan 2017 15:09:30 -0500 Subject: [PATCH 6/6] zmMemVerify attaches, so we need to zmMemInvalidate even if the shared data is no good --- scripts/zmtrigger.pl.in | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index f39dd3c35..ac1b9d752 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -117,7 +117,7 @@ use bytes; # ========================================================================== use constant MAX_CONNECT_DELAY => 10; -use constant MONITOR_RELOAD_INTERVAL => 30; +use constant MONITOR_RELOAD_INTERVAL => 300; use constant SELECT_TIMEOUT => 0.25; # ========================================================================== @@ -334,7 +334,7 @@ while( 1 ) ] ); - print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); + #print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); #print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); if ( $state == STATE_ALARM || $state == STATE_ALERT @@ -429,10 +429,8 @@ while( 1 ) # If necessary reload monitors if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )) { -print "TIme to reload Monitors " . join(',',keys %monitors ). "\n"; foreach my $monitor ( values(%monitors) ) { -print "imvalidating $$monitor{Id}\n"; # Free up any used memory handle zmMemInvalidate( $monitor ); } @@ -460,10 +458,11 @@ sub loadMonitors or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { - next - if ( !zmMemVerify( $monitor ) ) { -; # Check shared memory ok -} + # Check shared memory ok + if ( !zmMemVerify( $monitor ) ) { + zmMemInvalidate( $monitor ); + next; + } if ( defined($monitors{$monitor->{Id}}->{LastState}) ) {