2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

fixing 2 race conditions where a device is summarized as present instead of absent

git-svn-id: https://svn.fhem.de/fhem/trunk@2726 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
markusbloch 2013-02-14 19:51:11 +00:00
parent 7899db6196
commit 0f1e97717f
2 changed files with 44 additions and 9 deletions

View File

@ -36,7 +36,7 @@ use File::Basename;
use Getopt::Long;
use threads;
use Thread::Queue;
use Time::HiRes qw(gettimeofday);
use warnings;
use strict;
@ -241,6 +241,11 @@ while(1)
if(not $value =~ /^(absence|present)$/)
{
$handle{$uuid}{client}->send("$value;$room\n");
if($value eq "socket_closed")
{
delete($state{$uuid}{rooms}{$room});
}
}
else
{
@ -503,10 +508,11 @@ sub doQuery($$$)
my $selector;
my @client_handle;
my $reconnect_count = 0;
my $last_contact = gettimeofday();
my $previous_state = "absence";
my $current_state = "absence";
my $client_socket = new IO::Socket::INET (
PeerHost => $values{address},
@ -515,7 +521,7 @@ sub doQuery($$$)
Type => SOCK_STREAM,
KeepAlive => 1,
Blocking => 1
) or ( $log_queue->enqueue("$room: could not create socket to ".$values{address}." - $! - \n") and threads->exit());
) or ( $log_queue->enqueue("$room: could not create socket to ".$values{address}." - $! - \n"));
# if the thread gets a termination signal, the thread must be shutdown by itself
local $SIG{TERM} = sub {
@ -525,20 +531,36 @@ sub doQuery($$$)
threads->exit();
};
$selector = IO::Select->new($client_socket);
if($client_socket)
{
# send the given address to the presence daemon
$client_socket->send($do_address."|".$values{absence_timeout}."\n");
}
else
{
$selector->remove($client_socket);
$client_socket = undef;
# create a socket selector for non-blocking read and disconnect
$selector = IO::Select->new($client_socket);
}
# thread main loop
while(1)
{
if(defined($client_socket) and not $last_contact > (gettimeofday() - ($current_state eq "absence" ? $values{absence_timeout} : $values{presence_timeout}) - 60))
{
$log_queue->enqueue("$room: socket to ".$values{address}.":".$values{port}." did not report anything in expected time, resetting socket\n");
$selector->remove($client_socket);
close($client_socket);
$client_socket = undef;
}
if(not defined($client_socket))
{
# if it's the first occurance
@ -570,6 +592,9 @@ sub doQuery($$$)
# reset the reconnect counter
$reconnect_count = 0;
# set the last contact date to now
$last_contact = gettimeofday();
# add the new established socket to the IO selector for incoming data monitoring.
$selector->add($client_socket);
# send the given address to the presence daemon
@ -580,9 +605,11 @@ sub doQuery($$$)
sleep(9);
}
}
# if the socket has a message available
if(@client_handle = $selector->can_read(1))
{
# get all socket handles which has a message available
foreach my $local_client (@client_handle)
{
@ -592,6 +619,10 @@ sub doQuery($$$)
# if the message is defined (not EOF) handle the message...
if($return)
{
# set the last contact date
$last_contact = gettimeofday();
# remove trailing whitespaces and newlines
chomp($return);
@ -616,6 +647,8 @@ sub doQuery($$$)
# log the timout change to the log queue
$log_queue->enqueue("$room: changing to absence timeout (".$values{absence_timeout}.") for device $do_address\n");
$current_state = "absence";
# send the new command with the configured absence timeout
$local_client->send($do_address."|".$values{absence_timeout}."\n");
}
@ -623,6 +656,8 @@ sub doQuery($$$)
{
$log_queue->enqueue("$room: changing to presence timeout (".$values{presence_timeout}.") for device $do_address\n");
$current_state = "present";
# if the state changes from absence to present, set the presence timeout
$local_client->send($do_address."|".$values{presence_timeout}."\n");
}