Просмотр исходного кода

Only return valid results. Provide automatic clean up SAY zombies.

Zachary Kotlarek 13 лет назад
Родитель
Сommit
f569b49d91
1 измененных файлов с 41 добавлено и 1 удалено
  1. 41 1
      dmx/DMX.pm

+ 41 - 1
dmx/DMX.pm

@@ -1,6 +1,7 @@
 #!/usr/bin/perl
 #!/usr/bin/perl
 use strict;
 use strict;
 use warnings;
 use warnings;
+use POSIX;
 use File::Temp;
 use File::Temp;
 use IO::Select;
 use IO::Select;
 use IO::Socket::UNIX;
 use IO::Socket::UNIX;
@@ -45,6 +46,7 @@ if (!-d $DATA_DIR) {
 # State
 # State
 my $DMX_FH = undef();
 my $DMX_FH = undef();
 my $SELECT = undef();
 my $SELECT = undef();
+my %SAY    = ();
 
 
 # Data directory
 # Data directory
 sub dataDir() {
 sub dataDir() {
@@ -259,6 +261,9 @@ sub readState($$$$) {
 	my ($delay, $exists, $mtime, $valid) = @_;
 	my ($delay, $exists, $mtime, $valid) = @_;
 	my $cmdState = undef();
 	my $cmdState = undef();
 
 
+	# Cleanup previous say calls
+	sayCleanup();
+
 	# Wait for state updates
 	# Wait for state updates
 	my @ready_clients = $SELECT->can_read($delay);
 	my @ready_clients = $SELECT->can_read($delay);
 	foreach my $fh (@ready_clients) {
 	foreach my $fh (@ready_clients) {
@@ -269,6 +274,16 @@ sub readState($$$$) {
 		# Grab the inbound text
 		# Grab the inbound text
 		while (defined($fh->recv(my $text, $MAX_CMD_LEN))) {
 		while (defined($fh->recv(my $text, $MAX_CMD_LEN))) {
 
 
+			# Save the old data, in case the new stuff is bad
+			my %existsOld = ();
+			my %mtimeOld  = ();
+			if ($exists) {
+				%existsOld = %{$exists};
+			}
+			if ($mtime) {
+				%mtimeOld = %{$mtime};
+			}
+
 			# Parse the string
 			# Parse the string
 			my $state = parseState($text, $exists, $mtime);
 			my $state = parseState($text, $exists, $mtime);
 
 
@@ -282,6 +297,18 @@ sub readState($$$$) {
 				}
 				}
 			}
 			}
 
 
+			# Restore the old data, if the new stuff is bad
+			if (scalar(keys(%{$exists})) < 1) {
+				%{$exists} = ();
+				%{$mtime}  = ();
+				foreach my $key (keys(%existsOld)) {
+					$exists->{$key} = $existsOld{$key};
+				}
+				foreach my $key (keys(%mtimeOld)) {
+					$mtime->{$key} = $mtimeOld{$key};
+				}
+			}
+
 			# Propogate valid states
 			# Propogate valid states
 			if ($state) {
 			if ($state) {
 				$cmdState = $state;
 				$cmdState = $state;
@@ -293,20 +320,33 @@ sub readState($$$$) {
 	return $cmdState;
 	return $cmdState;
 }
 }
 
 
+# Reap zombie children
+sub sayCleanup() {
+	foreach my $pid (keys(%SAY)) {
+		waitpid($pid, POSIX::WNOHANG);
+		delete($SAY{$pid});
+	}
+}
+
 # Speak
 # Speak
 sub say($) {
 sub say($) {
 	my ($str) = @_;
 	my ($str) = @_;
-
 	if ($DEBUG) {
 	if ($DEBUG) {
 		print STDERR 'Say: ' . $str . "\n";
 		print STDERR 'Say: ' . $str . "\n";
 	}
 	}
 
 
+	# Cleanup previous say calls
+	sayCleanup();
+
+	# Fork and speak in the background
 	my $pid = fork();
 	my $pid = fork();
 	if (!defined($pid)) {
 	if (!defined($pid)) {
 		die('Unable to fork: ' . $! . "\n");
 		die('Unable to fork: ' . $! . "\n");
 	}
 	}
 	if (!$pid) {
 	if (!$pid) {
 		exec('say', $str);
 		exec('say', $str);
+	} else {
+		$SAY{$pid} = 1;
 	}
 	}
 }
 }