diff --git a/configure b/configure index effcda326..9b09cbcad 100755 --- a/configure +++ b/configure @@ -1821,7 +1821,7 @@ done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" -trap 'rm -fr `echo "Makefile src/Makefile web/Makefile web/zmconfig.php scripts/Makefile db/Makefile scripts/zmdc.pl scripts/zmx10.pl scripts/zmaudit.pl scripts/zmfilter.pl config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +trap 'rm -fr `echo "Makefile src/Makefile web/Makefile web/zmconfig.php scripts/Makefile db/Makefile scripts/zmdc.pl scripts/zmx10.pl scripts/zmaudit.pl scripts/zmfilter.pl scripts/zmwatch.pl config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then diff --git a/configure.in b/configure.in index 8203a88cd..3e57faaa8 100644 --- a/configure.in +++ b/configure.in @@ -73,5 +73,5 @@ AC_CHECK_LIB(dl,dlsym,,AC_MSG_ERROR(zm requires libdl.a)) AC_SUBST(bindir) -AC_OUTPUT(Makefile src/Makefile web/Makefile web/zmconfig.php scripts/Makefile db/Makefile scripts/zmdc.pl scripts/zmx10.pl scripts/zmaudit.pl scripts/zmfilter.pl) +AC_OUTPUT(Makefile src/Makefile web/Makefile web/zmconfig.php scripts/Makefile db/Makefile scripts/zmdc.pl scripts/zmx10.pl scripts/zmaudit.pl scripts/zmfilter.pl scripts/zmwatch.pl) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 2cca49e50..bc8a92e78 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -1,6 +1,5 @@ AUTOMAKE_OPTIONS = gnu -bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl +bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl zmwatch.pl EXTRA_DIST = $(bin_SCRIPTS) - diff --git a/scripts/Makefile.in b/scripts/Makefile.in index 6d9066b59..4671867e2 100644 --- a/scripts/Makefile.in +++ b/scripts/Makefile.in @@ -73,16 +73,16 @@ bindir = @bindir@ AUTOMAKE_OPTIONS = gnu -bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl +bin_SCRIPTS = zmdc.pl zmaudit.pl zmfilter.pl zmx10.pl zmwatch.pl EXTRA_DIST = $(bin_SCRIPTS) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h -CONFIG_CLEAN_FILES = zmdc.pl zmx10.pl zmaudit.pl zmfilter.pl +CONFIG_CLEAN_FILES = zmdc.pl zmx10.pl zmaudit.pl zmfilter.pl zmwatch.pl SCRIPTS = $(bin_SCRIPTS) DIST_COMMON = Makefile.am Makefile.in zmaudit.pl.in zmdc.pl.in \ -zmfilter.pl.in zmx10.pl.in +zmfilter.pl.in zmwatch.pl.in zmx10.pl.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) @@ -106,6 +106,8 @@ zmaudit.pl: $(top_builddir)/config.status zmaudit.pl.in cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status zmfilter.pl: $(top_builddir)/config.status zmfilter.pl.in cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status +zmwatch.pl: $(top_builddir)/config.status zmwatch.pl.in + cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) diff --git a/scripts/zmwatch.pl.z b/scripts/zmwatch.pl.z index d67eec01e..eb4800818 100755 --- a/scripts/zmwatch.pl.z +++ b/scripts/zmwatch.pl.z @@ -35,10 +35,11 @@ use constant DB_NAME => "zm"; use constant DB_USER => "zmadmin"; use constant DB_PASS => "zmadminzm"; -use constant CHECK_INTERVAL => 30; use constant COMMAND_PATH => '@prefix@/bin/'; -use constant ZM_SHM_KEY => 0x7a6d2000; use constant WATCH_LOG_FILE => '/tmp/zmwatch.log'; +use constant CHECK_INTERVAL => 10; # How often to check the FPS +use constant NUM_BAD_CHECKS => 3; # How many bad checks before we restart +use constant MIN_FPS => 0.5; # FPS at or below this are bad # ========================================================================== # @@ -69,13 +70,15 @@ select( STDERR ); $| = 1; select( LOG ); $| = 1; print( "Watchdog starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); -( $ENV{PATH} ) = ( $ENV{PATH} =~ /^(.*)$/ ); -( $ENV{BASH_ENV} ) = ( $ENV{BASH_ENV} =~ /^(.*)$/ ); +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my $dbh = DBI->connect( "DBI:mysql:".DB_NAME, DB_USER, DB_PASS ); my $sql = "select * from Monitors"; my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); +my %fps_hash; while( 1 ) { my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); @@ -83,36 +86,37 @@ while( 1 ) { if ( $monitor->{Function} ne 'None' ) { - my $device = $monitor->{Device}; - my $device_file = "/dev/video$device"; - # Check that the video device is readable - print( "Checking '$device_file'\n" ); - if ( !-R $device_file ) + my $fps_list = $fps_hash{$monitor->{Id}}; + if ( !$fps_list ) { - my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat(_); - $mode &= 07777; - if ( !$mode & 044 ) - { - print( "Device file '$device_file' unreadable, changing permissions\n" ); - chmod( $mode | 044, $device_file ) or die( "Can't chmod '$device_file': $!" ); - } + $fps_list = $fps_hash{$monitor->{Id}} = []; } - - # Check the write index is incrementing, if is isn't for 3 consecutive - # times we kill it and start again + # Check we are getting a decent FPS, if not then kill it my $command = COMMAND_PATH."zmu -m ".$monitor->{Id}." -f"; print( "Getting FPS for monitor $monitor->{Id} ('$command')\n" ); - if ( $command ) + my $fps = qx( $command ); + chomp($fps); + print( "Monitor $monitor->{Id} capturing at $fps FPS\n" ); + push( @$fps_list, $fps ); + if ( @$fps_list > NUM_BAD_CHECKS ) { - my $fps = qx( $command ); - print( "Monitor $monitor->{Id} capturing at $fps FPS\n" ); - if ( !$fps ) - { - my $command = COMMAND_PATH."zmdc.pl restart zmc -d ".$monitor->{Device}; - print( "Restarting capture daemon ('$command')\n" ); - print( qx( $command ) ); - } + pop( @$fps_list ); } + # See if we can find any good FPS readings + my @good_fps = grep { $_ > MIN_FPS } @$fps_list; + if ( @good_fps < NUM_BAD_CHECKS ) + { + print( "Monitor $monitor->{Id} has ".(NUM_BAD_CHECKS-int(@good_fps))." samples below ".MIN_FPS." FPS\n" ); + } + if ( @good_fps ) + { + # Yes, so continue + next; + } + # If we are here then something bad has happened + $command = COMMAND_PATH."zmdc.pl restart zmc -d ".$monitor->{Device}; + print( "Restarting capture daemon ('$command')\n" ); + print( qx( $command ) ); } } sleep( CHECK_INTERVAL ); diff --git a/src/Makefile.am b/src/Makefile.am index 91f65d532..393ca7dac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,19 +9,19 @@ cgidir = @CGI_PREFIX@ webuser = @WEB_USER@ webgroup = @WEB_GROUP@ -bin_PROGRAMS = zmc zma zmu zms +bin_PROGRAMS = zmc zma zmu zms zmfix zm_SOURCES = zm.cpp zmdbg.c jmemdst.c zmc_SOURCES = zmc.cpp $(zm_SOURCES) zma_SOURCES = zma.cpp $(zm_SOURCES) zms_SOURCES = zms.cpp $(zm_SOURCES) zmu_SOURCES = zmu.cpp $(zm_SOURCES) +zmfix_SOURCES = zmfix.cpp zmdbg.c noinst_HEADERS = zm.h zmcfg.h zmdbg.h jinclude.h font_6x11.h -EXTRA_DIST = - # Yes, you are correct. This is a HACK! install-exec-local: ( cd @bindir@; mv zms $(cgidir) ) ( cd $(cgidir); chown $(webuser):$(webgroup) zms ) + ( cd @bindir@; chmod u+s zmfix ) diff --git a/src/Makefile.in b/src/Makefile.in index 340bac543..00a81f819 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -82,17 +82,16 @@ cgidir = @CGI_PREFIX@ webuser = @WEB_USER@ webgroup = @WEB_GROUP@ -bin_PROGRAMS = zmc zma zmu zms +bin_PROGRAMS = zmc zma zmu zms zmfix zm_SOURCES = zm.cpp zmdbg.c jmemdst.c zmc_SOURCES = zmc.cpp $(zm_SOURCES) zma_SOURCES = zma.cpp $(zm_SOURCES) zms_SOURCES = zms.cpp $(zm_SOURCES) zmu_SOURCES = zmu.cpp $(zm_SOURCES) +zmfix_SOURCES = zmfix.cpp zmdbg.c noinst_HEADERS = zm.h zmcfg.h zmdbg.h jinclude.h font_6x11.h - -EXTRA_DIST = mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = @@ -118,6 +117,10 @@ zms_OBJECTS = zms.o zm.o zmdbg.o jmemdst.o zms_LDADD = $(LDADD) zms_DEPENDENCIES = zms_LDFLAGS = +zmfix_OBJECTS = zmfix.o zmdbg.o +zmfix_LDADD = $(LDADD) +zmfix_DEPENDENCIES = +zmfix_LDFLAGS = CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -136,9 +139,9 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = gtar GZIP_ENV = --best DEP_FILES = .deps/jmemdst.P .deps/zm.P .deps/zma.P .deps/zmc.P \ -.deps/zmdbg.P .deps/zms.P .deps/zmu.P -SOURCES = $(zmc_SOURCES) $(zma_SOURCES) $(zmu_SOURCES) $(zms_SOURCES) -OBJECTS = $(zmc_OBJECTS) $(zma_OBJECTS) $(zmu_OBJECTS) $(zms_OBJECTS) +.deps/zmdbg.P .deps/zmfix.P .deps/zms.P .deps/zmu.P +SOURCES = $(zmc_SOURCES) $(zma_SOURCES) $(zmu_SOURCES) $(zms_SOURCES) $(zmfix_SOURCES) +OBJECTS = $(zmc_OBJECTS) $(zma_OBJECTS) $(zmu_OBJECTS) $(zms_OBJECTS) $(zmfix_OBJECTS) all: all-redirect .SUFFIXES: @@ -207,6 +210,10 @@ zmu: $(zmu_OBJECTS) $(zmu_DEPENDENCIES) zms: $(zms_OBJECTS) $(zms_DEPENDENCIES) @rm -f zms $(CXXLINK) $(zms_LDFLAGS) $(zms_OBJECTS) $(zms_LDADD) $(LIBS) + +zmfix: $(zmfix_OBJECTS) $(zmfix_DEPENDENCIES) + @rm -f zmfix + $(CXXLINK) $(zmfix_LDFLAGS) $(zmfix_OBJECTS) $(zmfix_LDADD) $(LIBS) .cpp.o: $(CXXCOMPILE) -c $< @@ -388,6 +395,7 @@ maintainer-clean install-exec-local: ( cd @bindir@; mv zms $(cgidir) ) ( cd $(cgidir); chown $(webuser):$(webgroup) zms ) + ( cd @bindir@; chmod u+s zmfix ) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/zm.cpp b/src/zm.cpp index 74de06420..4d8498bfe 100644 --- a/src/zm.cpp +++ b/src/zm.cpp @@ -1603,10 +1603,11 @@ unsigned int Monitor::GetLastEvent() const double Monitor::GetFPS() const { int index1 = shared_images->last_write_index; - int index2 = (index1+1)%image_buffer_count;; + int index2 = (index1+1)%image_buffer_count; - Snapshot *snap1 = &image_buffer[index1]; - time_t time1 = *(snap1->timestamp); + //Snapshot *snap1 = &image_buffer[index1]; + //time_t time1 = *(snap1->timestamp); + time_t time1 = time( 0 ); Snapshot *snap2 = &image_buffer[index2]; time_t time2 = *(snap2->timestamp); diff --git a/src/zmfix.cpp b/src/zmfix.cpp index 3260ac2b7..d46586f83 100644 --- a/src/zmfix.cpp +++ b/src/zmfix.cpp @@ -118,6 +118,7 @@ int main( int argc, char *argv[] ) } mode |= mask; + Info(( "Resetting permission on %s to %o\n", device_path, mode )); if ( chmod( device_path, mode ) < 0 ) { Error(( "Can't chmod %s to %o: %s\n", device_path, mode, strerror(errno))); diff --git a/web/zmactions.php b/web/zmactions.php index ef89bc629..92bd7ef2a 100644 --- a/web/zmactions.php +++ b/web/zmactions.php @@ -281,8 +281,10 @@ if ( $action ) if ( !$result ) die( mysql_error() ); $monitor = mysql_fetch_assoc( $result ); + fixDevices(); zmcControl( $monitor, true ); zmaControl( $monitor, true ); + daemonControl( 'restart', 'zmwatch.pl' ); $refresh_parent = true; } } diff --git a/web/zmfuncs.php b/web/zmfuncs.php index 0960f6d71..a2ef6d359 100644 --- a/web/zmfuncs.php +++ b/web/zmfuncs.php @@ -77,6 +77,13 @@ function canStream() return( isNetscape() || (CAMBOZOLA_PATH && file_exists( CAMBOZOLA_PATH )) ); } +function fixDevices() +{ + $string = ZM_PATH."/zmfix"; + $string .= " 2>/dev/null >&- <&- >/dev/null"; + exec( $string ); +} + function daemonControl( $command, $daemon=false, $args=false ) { $string = ZM_PATH."/zmdc.pl $command"; diff --git a/web/zmhtml.php b/web/zmhtml.php index 9f36bacd2..c798586ee 100644 --- a/web/zmhtml.php +++ b/web/zmhtml.php @@ -53,6 +53,11 @@ switch( $view ) daemonControl( 'shutdown' ); } + if ( $start ) + { + fixDevices(); + } + header("Refresh: ".(($start||$stop)?1:REFRESH_MAIN)."; URL='$PHP_SELF'" ); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified @@ -113,6 +118,7 @@ switch( $view ) { daemonControl( 'start', 'zmx10.pl', '-c start' ); } + daemonControl( 'start', 'zmwatch.pl' ); } ?>