eval, alarm et curl

Le
Nicolas KOWALSKI
Bonjour,

J'essaie d'encapsuler l'appel à curl->perform() dans un bloc eval afin
de détecter un timeout. Le problème est que l'appel à curl->perform()
semble bloquant, c'est-à-dire que le timeout n'est détécté que lorsque
l'appel à cette fonction se termine. Je pensais que le bloc allait se
terminer au bout de temps imparti (30 secondes ici).

Qu'est-ce qui pourrait empêcher le 'alarm 30;' de fonctionner ?

Voici mon bout de code:

#!/usr/bin/perl

use strict;
use warnings;
use WWW::Curl::Easy;

#
# url to check
#
my $site = $ARGV[0];


#
# Initialize curl
#
my $curl = new WWW::Curl::Easy;
$curl->setopt(CURLOPT_URL, $site);
$curl->setopt(CURLOPT_HEADERFUNCTION, &header_callb);
$curl->setopt(CURLOPT_WRITEFUNCTION, &body_callb);


#
# return code of curl, or 28 if timeout
#
my $result = undef;


#
# start curl in eval block to detect timeout
#
eval {
local $SIG{ALRM} = sub { die "alarm" }; # NB: required
alarm 30;
$result = $curl->perform;
alarm 0;
};
if ($@ eq "alarm") {
$result = 28;
}


#
# Exit with computed exitcode
#
exit $result;


#
# Curl callbacks
#
sub body_callb {
my($chunk,$handle)=@_;
${handle} .= $chunk;
$body .= $chunk;
return length($chunk);
}

sub header_callb {
my($chunk,$handle)=@_;
${handle} .= $chunk;
$header .= $chunk;
return length($chunk);
}


Merci d'avance,
--
Nicolas
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Nicolas George
Le #147977
Nicolas KOWALSKI wrote in message
Qu'est-ce qui pourrait empêcher le 'alarm 30;' de fonctionner ?


Le système de gestion sûre des signaux, probablement.

my $curl = new WWW::Curl::Easy;
$curl->setopt(CURLOPT_URL, $site);
$curl->setopt(CURLOPT_HEADERFUNCTION, &header_callb);
$curl->setopt(CURLOPT_WRITEFUNCTION, &body_callb);


$curl->setopt(CURLOPT_TIMEOUT, 30);

ne marche pas ?

Nicolas KOWALSKI
Le #147976
On 8 août, 19:14, Nicolas George
Nicolas KOWALSKI wrote in message
Qu'est-ce qui pourrait empêcher le 'alarm 30;' de fonctionner ?


Le système de gestion sûre des signaux, probablement.


Ah, je ne connais pas. On peut désactiver ce système ?

my $curl = new WWW::Curl::Easy;
$curl->setopt(CURLOPT_URL, $site);
$curl->setopt(CURLOPT_HEADERFUNCTION, &header_callb);
$curl->setopt(CURLOPT_WRITEFUNCTION, &body_callb);


$curl->setopt(CURLOPT_TIMEOUT, 30);

ne marche pas ?


Globalement oui, mais le code de retour est "variable", ce qui est
vraiment génant dans mon cas, cf. http://thread.gmane.org/gmane.comp.web. curl.general/7871

--
Nicolas


Nicolas George
Le #147869
Nicolas KOWALSKI wrote in message
Ah, je ne connais pas. On peut désactiver ce système ?


Non. Et d'une manière générale, utiliser alarm pour implémenter un timeout
est très fortement déconseillé depuis des années.

Nicolas KOWALSKI
Le #147868
Nicolas George
Nicolas KOWALSKI wrote in message
Ah, je ne connais pas. On peut désactiver ce système ?


Non. Et d'une manière générale, utiliser alarm pour implémenter un timeout
est très fortement déconseillé depuis des années.


Ah, pourtant c'est indiqué dans le perldoc -f alarm. Pour que je me
mette à jour, quelle est la bonne méthode désormais ?

Merci,
--
Nicolas


Nicolas George
Le #147867
Nicolas KOWALSKI wrote in message
Nicolas George Ah, pourtant c'est indiqué dans le perldoc -f alarm. Pour que je me
mette à jour, quelle est la bonne méthode désormais ?


Il faut utiliser un timeout au niveau de l'appel système bloquant, avec poll
par exemple. Ce que fait curl avec l'option qui va bien. Mais si cette
option est buggée, c'est dommage. Ceci dit, j'ai lu ton thread sur
curl-general : si tout ce dont tu as à te plaindre, c'est de devoir tester
deux codes de retour au lieu d'un, franchement...

Nicolas KOWALSKI
Le #147866
Nicolas George
Il faut utiliser un timeout au niveau de l'appel système bloquant, avec poll
par exemple. Ce que fait curl avec l'option qui va bien. Mais si cette
option est buggée, c'est dommage. Ceci dit, j'ai lu ton thread sur
curl-general : si tout ce dont tu as à te plaindre, c'est de devoir tester
deux codes de retour au lieu d'un, franchement...


Au travail, je dois faire la différence entre en "connection refused"
et un "connection timeout", et avoir un retour variable n'aide
vraiment pas mes collègues ; d'un côté ce serait un service cassé, de
l'autre un firewall/switch vautré. Je souhaite juste leur faciliter la
vie, pas la mienne.

Merci pour ta réponse quand même,
--
Nicolas

Nicolas KOWALSKI
Le #147865
Nicolas George
Nicolas KOWALSKI wrote in message
Qu'est-ce qui pourrait empêcher le 'alarm 30;' de fonctionner ?


Le système de gestion sûre des signaux, probablement.

my $curl = new WWW::Curl::Easy;
$curl->setopt(CURLOPT_URL, $site);
$curl->setopt(CURLOPT_HEADERFUNCTION, &header_callb);
$curl->setopt(CURLOPT_WRITEFUNCTION, &body_callb);


$curl->setopt(CURLOPT_TIMEOUT, 30);


En fait, si : en combinant les deux tout simplement.

En fixant le timeout de curl à timeout+1, le timeout du bloc 'eval'
finit par "prendre le dessus", et j'ai alors le bon code de retour.

Sinon, je peux aussi utiliser Sys::SigAction::timeout_call pour faire
plus propre/moderne.

Merci,
--
Nicolas


Publicité
Poster une réponse
Anonyme