mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
Blocking.pl: add blockingCallMax attribute (Forum #56026)
git-svn-id: https://svn.fhem.de/fhem/trunk@11917 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
66d0bc87f8
commit
eec1c4f076
@ -24,9 +24,12 @@ sub BlockingCall($$@);
|
|||||||
sub BlockingExit();
|
sub BlockingExit();
|
||||||
sub BlockingKill($);
|
sub BlockingKill($);
|
||||||
sub BlockingInformParent($;$$);
|
sub BlockingInformParent($;$$);
|
||||||
|
sub BlockingStart(;$);
|
||||||
|
|
||||||
our $BC_telnetDevice;
|
our $BC_telnetDevice;
|
||||||
|
our %BC_hash;
|
||||||
my $telnetClient;
|
my $telnetClient;
|
||||||
|
my $bc_pid = 0;
|
||||||
|
|
||||||
sub
|
sub
|
||||||
BC_searchTelnet($)
|
BC_searchTelnet($)
|
||||||
@ -68,38 +71,83 @@ BlockingCall($$@)
|
|||||||
{
|
{
|
||||||
my ($blockingFn, $arg, $finishFn, $timeout, $abortFn, $abortArg) = @_;
|
my ($blockingFn, $arg, $finishFn, $timeout, $abortFn, $abortArg) = @_;
|
||||||
|
|
||||||
|
my %h = ( pid=>'WAITING:', fn=>$blockingFn, arg=>$arg, finishFn=>$finishFn,
|
||||||
|
timeout=>$timeout, abortFn=>$abortFn, abortArg=>$abortArg );
|
||||||
|
$BC_hash{++$bc_pid} = \%h;
|
||||||
|
$h{bc_pid} = $bc_pid;
|
||||||
|
return BlockingStart(\%h);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
BlockingStart(;$)
|
||||||
|
{
|
||||||
|
my ($curr) = @_;
|
||||||
|
|
||||||
|
if($curr && $curr =~ m/^\d+$/) {
|
||||||
|
delete($BC_hash{$curr});
|
||||||
|
$curr = undef;
|
||||||
|
}
|
||||||
|
|
||||||
# Look for the telnetport. Must be done before forking to be able to create a
|
# Look for the telnetport. Must be done before forking to be able to create a
|
||||||
# temporary device. Do it each time, as the old telnet may got a password
|
# temporary device. Do it each time, as the old telnet may got a password
|
||||||
BC_searchTelnet($blockingFn);
|
BC_searchTelnet($curr && $curr->{fn} ? $curr->{fn}: "BlockingStart");
|
||||||
|
|
||||||
# do fork
|
my $chld_alive = 0;
|
||||||
my $pid = fhemFork;
|
my $max = AttrVal('global', 'blockingCallMax', 0);
|
||||||
if(!defined($pid)) {
|
|
||||||
Log 1, "Cannot fork: $!";
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($pid) {
|
for my $bpid (sort { $a <=> $b} keys %BC_hash) {
|
||||||
Log 4, "BlockingCall ($blockingFn): created child ($pid), ".
|
my $h = $BC_hash{$bpid};
|
||||||
"uses $BC_telnetDevice to connect back";
|
|
||||||
my %h = ( pid=>$pid, fn=>$blockingFn, finishFn=>$finishFn,
|
if($h->{pid} !~ m/:/) {
|
||||||
abortFn=>$abortFn, abortArg=>$abortArg );
|
if(!kill(0, $h->{pid})) {
|
||||||
if($timeout) {
|
$h->{pid} = "DEAD:$h->{pid}";
|
||||||
InternalTimer(gettimeofday()+$timeout, "BlockingKill", \%h, 0);
|
delete($BC_hash{$bpid});
|
||||||
|
} else {
|
||||||
|
$chld_alive++;
|
||||||
|
}
|
||||||
|
next;
|
||||||
}
|
}
|
||||||
return \%h;
|
|
||||||
|
if($max && $chld_alive >= $max) {
|
||||||
|
if($curr && $curr->{fn}) {
|
||||||
|
Log 4, "BlockingCall ($curr->{fn}) enqueue: ".
|
||||||
|
"limit (blockingCallMax=$max) reached";
|
||||||
|
}
|
||||||
|
RemoveInternalTimer(\%BC_hash);
|
||||||
|
InternalTimer(gettimeofday()+5, "BlockingStart", \%BC_hash, 0);
|
||||||
|
return $curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# do fork
|
||||||
|
my $pid = fhemFork;
|
||||||
|
if(!defined($pid)) {
|
||||||
|
Log 1, "Cannot fork: $!";
|
||||||
|
return $curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($pid) {
|
||||||
|
Log 4, "BlockingCall ($h->{fn}): created child ($pid), ".
|
||||||
|
"uses $BC_telnetDevice to connect back";
|
||||||
|
$h->{pid} = $pid;
|
||||||
|
InternalTimer(gettimeofday()+$h->{timeout}, "BlockingKill", $h, 0)
|
||||||
|
if($h->{timeout});
|
||||||
|
$chld_alive++;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Child here
|
||||||
|
no strict "refs";
|
||||||
|
my $ret = &{$h->{fn}}($h->{arg});
|
||||||
|
use strict "refs";
|
||||||
|
|
||||||
|
BlockingInformParent("BlockingStart", $h->{bc_pid}, 0) if($max);
|
||||||
|
BlockingExit() if(!$h->{finishFn});
|
||||||
|
|
||||||
|
# Write the data back, calling the function
|
||||||
|
BlockingInformParent($h->{finishFn}, $ret, 0);
|
||||||
|
BlockingExit();
|
||||||
}
|
}
|
||||||
|
return $curr;
|
||||||
# Child here
|
|
||||||
no strict "refs";
|
|
||||||
my $ret = &{$blockingFn}($arg);
|
|
||||||
use strict "refs";
|
|
||||||
|
|
||||||
BlockingExit() if(!$finishFn);
|
|
||||||
|
|
||||||
# Write the data back, calling the function
|
|
||||||
BlockingInformParent($finishFn, $ret, 0);
|
|
||||||
BlockingExit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
@ -162,7 +210,7 @@ BlockingKill($)
|
|||||||
wait if($^O =~ m/Win/);
|
wait if($^O =~ m/Win/);
|
||||||
|
|
||||||
if($^O !~ m/Win/) {
|
if($^O !~ m/Win/) {
|
||||||
if($h->{pid} && kill(9, $h->{pid})) {
|
if($h->{pid} && $h->{pid} !~ m/:/ && kill(9, $h->{pid})) {
|
||||||
Log 1, "Timeout for $h->{fn} reached, terminated process $h->{pid}";
|
Log 1, "Timeout for $h->{fn} reached, terminated process $h->{pid}";
|
||||||
if($h->{abortFn}) {
|
if($h->{abortFn}) {
|
||||||
no strict "refs";
|
no strict "refs";
|
||||||
|
@ -1351,6 +1351,12 @@ The following local attributes are used by a wider range of devices:
|
|||||||
</ul>
|
</ul>
|
||||||
</li><br>
|
</li><br>
|
||||||
|
|
||||||
|
<a name="blockingCallMax"></a>
|
||||||
|
<li>blockingCallMax<br>
|
||||||
|
Limit the number of parallel running processes started by the
|
||||||
|
BlockingCall FHEM helper routine. Useful on limited hardware.
|
||||||
|
</li><br>
|
||||||
|
|
||||||
<a name="configfile"></a>
|
<a name="configfile"></a>
|
||||||
<li>configfile<br>
|
<li>configfile<br>
|
||||||
Contains the name of the fhem configuration file. If <a
|
Contains the name of the fhem configuration file. If <a
|
||||||
|
@ -1381,6 +1381,13 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
|
|||||||
</ul>
|
</ul>
|
||||||
</li><br>
|
</li><br>
|
||||||
|
|
||||||
|
<a name="blockingCallMax"></a>
|
||||||
|
<li>blockingCallMax<br>
|
||||||
|
Begrenzt die Anzahl der parallel laufenden Prozesse, die von der
|
||||||
|
BlockingCall FHEM Hilfsroutine gestartet wurden. Sinnvoll auf weniger
|
||||||
|
leistungsfaehigen Hardware.
|
||||||
|
</li><br>
|
||||||
|
|
||||||
<a name="configfile"></a>
|
<a name="configfile"></a>
|
||||||
<li>configfile<br>
|
<li>configfile<br>
|
||||||
Enthält den Namen der FHEM Konfigurationsdatei. Wenn <a
|
Enthält den Namen der FHEM Konfigurationsdatei. Wenn <a
|
||||||
|
@ -272,6 +272,7 @@ my @globalAttrList = qw(
|
|||||||
backupcmd
|
backupcmd
|
||||||
backupdir
|
backupdir
|
||||||
backupsymlink
|
backupsymlink
|
||||||
|
blockingCallMax
|
||||||
configfile
|
configfile
|
||||||
dnsServer
|
dnsServer
|
||||||
dupTimeout
|
dupTimeout
|
||||||
|
Loading…
x
Reference in New Issue
Block a user