Ich versuche, eine Anfrage an einen unzuverlässigen Server zu implementieren. Die Anfrage ist eine nette Sache, aber nicht 100% erforderlich, damit mein Perl-Skript erfolgreich abgeschlossen werden kann. Das Problem ist, dass der Server gelegentlich blockiert (wir versuchen herauszufinden, warum) und die Anfrage wird niemals erfolgreich sein. Da der Server denkt, dass es live ist, hält es die Socket-Verbindung offen, so dass der Timeout-Wert von LWP :: UserAgent uns nicht gut tut. Was ist der beste Weg, um eine absolute Zeitüberschreitung bei einer Anfrage zu erzwingen?True Timeout auf LWP :: UserAgent Anfrage Methode
FYI, das ist kein DNS-Problem. Der Deadlock hat etwas mit einer großen Anzahl von Updates zu tun, die gleichzeitig unsere Postgres-Datenbank betreffen. Zu Testzwecken haben wir im Server-Antworthandler im Wesentlichen eine while (1) {} -Zeile gesetzt.
Derzeit sieht der Code wie folgt:
my $ua = LWP::UserAgent->new;
ua->timeout(5); $ua->cookie_jar({});
my $req = HTTP::Request->new(POST => "http://$host:$port/auth/login");
$req->content_type('application/x-www-form-urlencoded');
$req->content("login[user]=$username&login[password]=$password");
# This line never returns
$res = $ua->request($req);
Ich habe versucht, Signale mit einem Timeout auslösen, aber das scheint nicht zu funktionieren.
Die endgültige Antwort, die ich verwenden werde, wurde von jemandem offline vorgeschlagen, aber ich werde es hier erwähnen. Aus irgendeinem Grund funktioniert SigAction, während $ SIG (ALRM) nicht funktioniert. Immer noch nicht sicher, warum, aber das wurde getestet, um zu funktionieren. Hier sind zwei Arbeitsvarianten:
# Takes a LWP::UserAgent, and a HTTP::Request, returns a HTTP::Request
sub ua_request_with_timeout {
my $ua = $_[0];
my $req = $_[1];
# Get whatever timeout is set for LWP and use that to
# enforce a maximum timeout per request in case of server
# deadlock. (This has happened.)
use Sys::SigAction qw(timeout_call);
our $res = undef;
if(timeout_call(5, sub {$res = $ua->request($req);})) {
return HTTP::Response->new(408); #408 is the HTTP timeout
} else {
return $res;
}
}
sub ua_request_with_timeout2 {
print "ua_request_with_timeout\n";
my $ua = $_[0];
my $req = $_[1];
# Get whatever timeout is set for LWP and use that to
# enforce a maximum timeout per request in case of server
# deadlock. (This has happened.)
my $timeout_for_client = $ua->timeout() - 2;
our $socket_has_timedout = 0;
use POSIX;
sigaction SIGALRM, new POSIX::SigAction(
sub {
$socket_has_timedout = 1;
die "alarm timeout";
}
) or die "Error setting SIGALRM handler: $!\n";
my $res = undef;
eval {
alarm ($timeout_for_client);
$res = $ua->request($req);
alarm(0);
};
if ($socket_has_timedout) {
return HTTP::Response->new(408); #408 is the HTTP timeout
} else {
return $res;
}
}
Mögliche Duplikat [Wie eine bestimmte Timeout in Perl erzwingen?] (Http://stackoverflow.com/questions/15899855/how-to-enforce-a -definite-timeout-in-perl) – sixtyfootersdude