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:
parent
7899db6196
commit
0f1e97717f
@ -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");
|
||||
}
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user