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

HttpUtils: extend timeout in blocking situations (Forum #54697)

git-svn-id: https://svn.fhem.de/fhem/trunk@11715 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2016-06-25 15:26:33 +00:00
parent 989445d5c2
commit bdc12f8b12
2 changed files with 46 additions and 31 deletions

View File

@ -73,19 +73,21 @@ HttpUtils_Close($)
}
sub
HttpUtils_Err($$)
HttpUtils_Err($)
{
my ($hash, $errtxt) = @_;
$hash = $hash->{hash};
my ($lhash, $errtxt) = @_;
my $hash = $lhash->{hash};
if($lhash->{sts} && $lhash->{sts} == $selectTimestamp) { # busy loop check
Log 4, "extending '$lhash->{msg} $hash->{addr}' timeout due to busy loop";
InternalTimer(gettimeofday()+1, "HttpUtils_Err", $lhash);
return;
}
return if(!defined($hash->{FD})); # Already closed
HttpUtils_Close($hash);
$hash->{callback}($hash, "$errtxt $hash->{addr} timed out", "");
$hash->{callback}($hash, "$lhash->{msg} $hash->{addr} timed out", "");
}
sub HttpUtils_ConnErr($) { my ($hash) = @_; HttpUtils_Err($hash, "connect to");}
sub HttpUtils_ReadErr($) { my ($hash) = @_; HttpUtils_Err($hash, "read from"); }
sub HttpUtils_WriteErr($){ my ($hash) = @_; HttpUtils_Err($hash, "write to"); }
sub
HttpUtils_File($)
{
@ -154,11 +156,10 @@ HttpUtils_gethostbyname($$$)
my %dh = ( conn=>$c, FD=>$c->fileno(), NAME=>"DNS", origHash=>$hash,
addr=>$dnsServer, callback=>$fn );
my %timerHash = ( hash => \%dh );
my %timerHash = ( hash=>\%dh, msg=>"DNS" );
my $bhost = join("", map { pack("CA*",length($_),$_) } split(/\./, $host));
my $qry = pack("nnnnnn", 0x7072,0x0100,1,0,0,0) . $bhost . pack("Cnn", 0,1,1);
my $ql = length($qry);
my $dnsTo = 0.25;
$dh{directReadFn} = sub() { # Parse the answer
RemoveInternalTimer(\%timerHash);
@ -177,17 +178,20 @@ HttpUtils_gethostbyname($$$)
$selectlist{\%dh} = \%dh;
my $dnsQuery;
my $dnsTo = 0.25;
my $lSelectTs = $selectTimestamp;
$dnsQuery = sub()
{
$dnsTo *= 2;
return HttpUtils_Err(\%timerHash, "DNS") if($dnsTo > $hash->{timeout}/2);
$dnsTo *= 2 if($lSelectTs != $selectTimestamp);
$lSelectTs = $selectTimestamp;
return HttpUtils_Err(\%timerHash) if($dnsTo > $hash->{timeout}/2);
my $ret = syswrite $dh{conn}, $qry;
if(!$ret || $ret != $ql) {
my $err = $!;
HttpUtils_Close(\%dh);
return $fn->($hash, "DNS write error: $err", undef);
}
InternalTimer(gettimeofday()+$dnsTo, $dnsQuery, \%timerHash, 0);
InternalTimer(gettimeofday()+$dnsTo, $dnsQuery, \%timerHash);
};
$dnsQuery->();
@ -241,7 +245,7 @@ HttpUtils_Connect($)
(int($!)==140 && $^O eq "MSWin32")) { # Nonblocking connect
$hash->{FD} = $hash->{conn}->fileno();
my %timerHash = ( hash => $hash );
my %timerHash=(hash=>$hash,sts=>$selectTimestamp,msg=>"connect to");
$hash->{directWriteFn} = sub() {
delete($hash->{FD});
delete($hash->{directWriteFn});
@ -262,7 +266,7 @@ HttpUtils_Connect($)
$hash->{NAME}="" if(!defined($hash->{NAME}));#Delete might check it
$selectlist{$hash} = $hash;
InternalTimer(gettimeofday()+$hash->{timeout},
"HttpUtils_ConnErr", \%timerHash, 0);
"HttpUtils_Err", \%timerHash);
return undef;
} else {
$hash->{callback}($hash, "connect to $hash->{addr}: $!", "");
@ -379,7 +383,7 @@ HttpUtils_Connect2($)
$hash->{FD} = $hash->{conn}->fileno();
$hash->{buf} = "";
$hash->{NAME} = "" if(!defined($hash->{NAME}));
my %timerHash = ( hash => $hash );
my %timerHash = (hash=>$hash, checkSTS=>$selectTimestamp, msg=>"write to");
$hash->{directReadFn} = sub() {
my $buf;
my $len = sysread($hash->{conn},$buf,65536);
@ -409,13 +413,13 @@ HttpUtils_Connect2($)
shutdown($hash->{conn}, 1) if($s);
delete($hash->{directWriteFn});
RemoveInternalTimer(\%timerHash);
$timerHash{msg} = "read from";
InternalTimer(gettimeofday()+$hash->{timeout},
"HttpUtils_ReadErr", \%timerHash, 0);
"HttpUtils_Err", \%timerHash);
}
};
$selectlist{$hash} = $hash;
InternalTimer(gettimeofday()+$hash->{timeout},
"HttpUtils_WriteErr", \%timerHash, 0);
InternalTimer(gettimeofday()+$hash->{timeout}, "HttpUtils_Err",\%timerHash);
return undef;
} else {

View File

@ -198,13 +198,19 @@ sub cfgDB_WriteFile($@);
# VOLATILE- Set if the definition should be saved to the "statefile"
# NOTIFYDEV - if set, the notifyFn will only be called for this device
use vars qw($auth_refresh);
use vars qw($cmdFromAnalyze); # used by the warnings-sub
use vars qw($cvsid); # used in 98_version.pm
use vars qw($devcount); # Maximum device number, used for storing
use vars qw($featurelevel);
use vars qw($fhem_started); # used for uptime calculation
use vars qw($init_done); #
use vars qw($internal_data); # FileLog/DbLog -> SVG data transport
use vars qw($lastDefChange); # number of last def/attr change
use vars qw($nextat); # Time when next timer will be triggered.
use vars qw($readytimeout); # Polling interval. UNIX: device search only
use vars qw($reread_active);
use vars qw($selectTimestamp); # used to check last select exit timestamp
use vars qw($winService); # the Windows Service object
use vars qw(%attr); # Attributes
use vars qw(%cmds); # Global command name hash.
@ -212,22 +218,19 @@ use vars qw(%data); # Hash for user data
use vars qw(%defaultattr); # Default attributes, used by FHEM2FHEM
use vars qw(%defs); # FHEM device/button definitions
use vars qw(%inform); # Used by telnet_ActivateInform
use vars qw(%logInform); # Used by FHEMWEB/Event-Monitor
use vars qw(%intAt); # Internal at timer hash, global for benchmark
use vars qw(%logInform); # Used by FHEMWEB/Event-Monitor
use vars qw(%modules); # List of loaded modules (device/log/etc)
use vars qw(%ntfyHash); # hash of devices needed to be notified.
use vars qw(%oldvalue); # Old values, see commandref.html
use vars qw(%readyfnlist); # devices which want a "readyfn"
use vars qw(%selectlist); # devices which want a "select"
use vars qw(%value); # Current values, see commandref.html
use vars qw($lastDefChange); # number of last def/attr change
use vars qw(@structChangeHist); # Contains the last 10 structural changes
use vars qw($cmdFromAnalyze); # used by the warnings-sub
use vars qw($featurelevel);
use vars qw(@authorize); # List of authorization devices
use vars qw(@authenticate); # List of authentication devices
use vars qw($auth_refresh);
use vars qw($cvsid); # used in 98_version.pm
use vars qw(@authorize); # List of authorization devices
use vars qw(@structChangeHist); # Contains the last 10 structural changes
$selectTimestamp = gettimeofday();
$cvsid = '$Id$';
my $AttrList = "verbose:0,1,2,3,4,5 room group comment:textField-long alias ".
@ -2767,7 +2770,10 @@ HandleTimeout()
return undef if(!$nextat);
my $now = gettimeofday();
return ($nextat-$now) if($now < $nextat);
if($now < $nextat) {
$selectTimestamp = $now;
return ($nextat-$now);
}
$now += 0.01;# need to cover min delay at least
$nextat = 0;
@ -2792,9 +2798,14 @@ HandleTimeout()
}
}
return undef if(!$nextat);
$now = gettimeofday(); # possibly some tasks did timeout in the meantime
# we will cover them
if(!$nextat) {
$selectTimestamp = $now;
return undef;
}
$now = gettimeofday(); # if some callbacks took longer
$selectTimestamp = $now;
return ($now+ 0.01 < $nextat) ? ($nextat-$now) : 0.01;
}