Timeout-Problem

28/05/2009 - 10:53 von Ferry Bolhar | Report spam
Hallo,

ich habe folgendes Problem auf einer RH ES5 Kiste.

Gegeben sei der Code:

$SIG{ALRM} = sub {die '!'};

eval {
alarm $secs;
$ans = $ua->request($req);
alarm 0;
};

send('Request timed out') if $@;

Das Ganze ist Teil eines Codes, der via LWP CGI-Seiten abfragt. Da bei
diesen Abfragen Proxy- und SSL-Server beteiligt sind, die hàufig langsam
sind oder ganz "hàngen", habe ich die eigentliche Abfrage in ein eval
gestellt, innerhalb dessen mittels "alarm" ein Timeout ($secs enthàlt die
entsprechende Sekundenzahl) eingerichtet und abgebrochen wird, wenn es zu
einer Zeitüberschreitung kommt. Der Alarm-Trap wurd durch Setzen von
$SIG{ALRM} abgefangen und durch das "die" $@ gesetzt. Nach dem "eval" ist $@
dann nicht leer und es wird eine entsprechende Meldung generiert und in der
Programmlogik weiterverarbeitet.

Dies funktioniert in 95% aller Fàlle. Manchmal kommt es allerdings vor, dass
der Aufruf der request-Methode trotzdem hàngen bleibt, d.h. der Alarm-Trap
kommt dann nicht durch. Dazu meine Fragen:

o-) Weiß jemand, warum das so ist?
o-) Was kann man (von Perl aus) dagegen tun?

Es ist mir klar, dass das möglicherweise kein Perl-Problem ist, sondern ein
Problem des Betriebssystems. Trotzdem wàre es hilfreich zu erfahren, ob es
eine Lösung dafür gibt, z.B. durch Setzen bestimmter Parameter, durch
Verwenden von ioctl() oder durch direktes Verwenden von Socketcalls statt
LWP? Wer weiß etwas bzw. hatte dieses Problem auch schon?

Vielen Dank & schöne Grüße aus Wien

F. Bolhar

Ing. Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: ferdinand.bolhar-nordenkampf@wien.gv.at
 

Lesen sie die antworten

#1 A. Sicken
28/05/2009 - 19:12 | Warnen spam
Ferry Bolhar wrote:

Hallo,

ich habe folgendes Problem auf einer RH ES5 Kiste.

Gegeben sei der Code:

$SIG{ALRM} = sub {die '!'};

eval {
alarm $secs;
$ans = $ua->request($req);
alarm 0;
};

send('Request timed out') if $@;



Hallo,

mir würden auf Anhieb zwei mögliche Probleme zu deinem Skript einfallen:

a) die Empfehlung local($SIG{'ALRM'}) = sub ... zu verwenden und
b) den Zeitwert vor dem Setzen, außerhalb von eval() auszulesen und
zwischenzuspeichern, damit in dem Unterprogramm zum Abfangen ein Wert zum
restaturieren des ursprünglichen Wertes zur Verfügung steht. Die erste und
wichtigste Sache aber ist, im Unterprogramm: $SIG{'ALRM'} = IGNORE.

Der Punkt a) sorgt dafür, dass dar Ereignishandler nicht überschrieben wird,
zB. durch das Pragma Carp oder das CGI-Modul. Auch andere Module (gerade im
Netzbereich) arbeiten mit Signalhandlern und modifiezieren diese.

Der Punkt b) ist wichtig, den es kann (muss aber nicht) vorkommen, das die
Verarbeitung (gerade im Netzbereich) lànger dauert und dieser Signalhandler
wiederholt zuschlàgt...

Anzumerken wàre noch, das gerade bei Signalhandlern sehr wichtig ist, in
welcher Herachie (Modul -> Vererbung etc) sie deklariert (erzeugt) und in
welcher sie dann generiert werden...

Signalhandler sind eine verwirrende Sache...

Gruß
Andreas

Ähnliche fragen