J'essaie d'implémenter une requête auprès d'un serveur non fiable. La requête est agréable à avoir, mais pas 100% requis pour que mon script perl se termine avec succès. Le problème est que le serveur va parfois se bloquer (nous essayons de comprendre pourquoi) et la requête ne réussira jamais. Puisque le serveur pense qu'il est en ligne, il maintient la connexion socket ouverte, ainsi la valeur de timeout de LWP :: UserAgent ne nous sert à rien. Quelle est la meilleure façon d'imposer un délai d'attente absolu sur une demande?True timeout sur la méthode de requête LWP :: UserAgent
FYI, ce n'est pas un problème DNS. L'impasse a quelque chose à voir avec un grand nombre de mises à jour qui touchent notre base de données Postgres en même temps. À des fins de test, nous avons essentiellement mis une ligne while (1) {} dans le gestionnaire de réponse des serveurs.
Actuellement, le code ressemble à ceci:
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);
J'ai essayé d'utiliser des signaux pour déclencher un délai d'attente, mais cela ne semble pas fonctionner. La réponse finale que je vais utiliser a été proposée par quelqu'un hors ligne, mais je vais le mentionner ici. Pour une raison quelconque, SigAction fonctionne alors que $ SIG (ALRM) ne fonctionne pas. Je ne sais toujours pas pourquoi, mais cela a été testé pour fonctionner. Voici deux versions fonctionnelles:
# 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;
}
}
double possible de [Comment faire respecter un délai d'attente défini en perl?] (Http://stackoverflow.com/questions/15899855/how-to-enforce-a -definite-timeout-in-perl) – sixtyfootersdude