Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

eval, alarm et curl

7 réponses
Avatar
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\n" }; # NB: \n required
alarm 30;
$result = $curl->perform;
alarm 0;
};
if ($@ eq "alarm\n") {
$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

7 réponses

Avatar
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);

ne marche pas ?

Avatar
Nicolas KOWALSKI
On 8 août, 19:14, Nicolas George <nicolas$ wrote:
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


Avatar
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.

Avatar
Nicolas KOWALSKI
Nicolas George <nicolas$ writes:

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


Avatar
Nicolas George
Nicolas KOWALSKI wrote in message :
Nicolas George <nicolas$ writes:
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...

Avatar
Nicolas KOWALSKI
Nicolas George <nicolas$ writes:

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

Avatar
Nicolas KOWALSKI
Nicolas George <nicolas$ writes:

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