alarm() und LWP: timeout()
Wolfgang Wiese
- perl
Hallo,
Hintergrundsituation:
ich hab einen lang laufenden Prozess der eine bestimmte
Timeout X mit alarm(X); gesetzt hat.
Dieser Prozess ruft nun LWP auf, welcher einzelne bis viele
URLs sammeln soll (ja, ein Spider).
Nun moechte ich bei diesen LWP-Gets auch die dortige Timeout-Funktion benutzen
(und muss es sogar weil einige URLs Probleme machen)...
Aber anscheinend geht dies nicht, denn:
(LWP::UserAgent):
...
if ($use_alarm) {
$SIG{'ALRM'} = sub {
LWP::Debug::trace('timeout');
die 'Timeout';
};
$protocol->timeout($timeout);
alarm($timeout);
}
...
Die Manual zu 'alarm' sagt aber:
"Alarm requests are not stacked; successive calls reset the
alarm clock of the calling process. "
Weiter steht da was nettes ueber LWP (warum steht das nicht in perldoc LWP, verdammich??!):
" o if the calling thread is a bound thread, the resulting
SIGALRM is delivered to the bound thread's LWP, i.e. to
the calling thread. There is a bug currently that this
signal is not maskable via thr_sigsetmask(3T) on this
bound thread.
o if the calling thread is an unbound thread, the resulting
SIGALRM is sent to the LWP on which the thread was running
when it issued the call to alarm(). This is neither a
per-process semantic, nor a per-thread semantic, since the
LWP could change threads after the call to alarm() but
before the SIGALRM delivery, causing some other thread to
get it possibly. Hence this is basically a bug.
"
In anderen Worten: Ich kann nicht in meinen Programm alarm() nutzen UND
gleichzeitig von LWP die Timeout-Funktion eingeschaltet lassen (per default ist diese
uebrigens an!).
Lange Rede, kurzer Sinn: Hat jemand eine Ahnung, wie ich dies
umgehen kann, also sowohl alarm() in meinem Hauptprogramm,
als auch den von LWP gleichzeitig nutzen?
(Immer im Hinterkopf, das die Alarmzeit vom
Hauptprogramm != Timeout von LWP)
Ciao,
Wolfgang
Lange Rede, kurzer Sinn: Hat jemand eine Ahnung, wie ich dies
umgehen kann, also sowohl alarm() in meinem Hauptprogramm,
als auch den von LWP gleichzeitig nutzen?
Nein,
vgl. Thread: http://www.ics.uci.edu/pub/websoft/libwww-perl/archive/1998h1/0026.html
Sinn in deinem Tun sehe ich übrigens immernoch nicht...
Lange Rede, kurzer Sinn: Hat jemand eine Ahnung, wie ich dies
umgehen kann, also sowohl alarm() in meinem Hauptprogramm,
als auch den von LWP gleichzeitig nutzen?Nein,
vgl. Thread: http://www.ics.uci.edu/pub/websoft/libwww-perl/archive/1998h1/0026.htmlSinn in deinem Tun sehe ich übrigens immernoch nicht...
Troll >:)
Du hast nicht verstanden was ich wollte, bzw. was ich schreib.
Sonst haettest du mir nicht den obigen Link gegeben, hinter dem übrigens auch kein
Thread steht; Bzw. der Thread besteht nur aus einer Frage die ich oben bereits selbst
beantwortet habe....
Was ist daran ungewoehnlich ein Programm zu haben, welches ein eigens Timeout hat
und das dennoch auf LWP zugreifen möchte, ohne das die eigne Timeoutfunktion
in Mitleidenschaft gezogen wird?
Ciao,
Wolfgang
Lange Rede, kurzer Sinn: Hat jemand eine Ahnung, wie ich dies
umgehen kann, also sowohl alarm() in meinem Hauptprogramm,
als auch den von LWP gleichzeitig nutzen?Nein,
vgl. Thread: http://www.ics.uci.edu/pub/websoft/libwww-perl/archive/1998h1/0026.html
Du hast nicht verstanden was ich wollte, bzw. was ich schreib.
Doch.
Sonst haettest du mir nicht den obigen Link gegeben, hinter dem übrigens auch kein
Thread steht; Bzw. der Thread besteht nur aus einer Frage die ich oben bereits selbst
beantwortet habe....
Kein Thread? Hm, dann existiert z.B. http://www.ics.uci.edu/pub/websoft/libwww-perl/archive/1998h1/0036.html auch gar nicht...
Was ist daran ungewoehnlich ein Programm zu haben, welches ein eigens Timeout hat
und das dennoch auf LWP zugreifen möchte, ohne das die eigne Timeoutfunktion
in Mitleidenschaft gezogen wird?
Deine Begründung fand ich nur sehr merkwürdig. Bei meinem flüchtigen lesen klang es stark danach, dass du LWP selber 'outtimen' wolltest, statt die eigene timeout() methode zu benutzen.
Kein Thread? Hm, dann existiert z.B. http://www.ics.uci.edu/pub/websoft/libwww-perl/archive/1998h1/0036.html auch gar nicht...
Seltsames Forum. Als ich bei obigen Link auf "Next Message" ging, war da
irgenteine andere Message und unter Thread war nur ein Index, aber nicht das was
ich als Thread betrachte (Thread=Alle Nachrichten zu einem Thema)
Aber auch die Antwort von Gisle Aas ist bei mir nicht hilfreich, weil ich das bereits wußte
und garnicht wissen wollte.
Was ist daran ungewoehnlich ein Programm zu haben, welches ein eigens Timeout hat
und das dennoch auf LWP zugreifen möchte, ohne das die eigne Timeoutfunktion
in Mitleidenschaft gezogen wird?Deine Begründung fand ich nur sehr merkwürdig. Bei meinem flüchtigen lesen klang es stark
danach, dass du LWP selber 'outtimen' wolltest, statt die eigene timeout() methode zu benutzen.
Nein!
Also nochmal:
LWP nutzt in der am weitesten verbreiteten Version alarm().
Mein Programm, welches LWP nutzt, benutzt aber selbst schon alarm() für andere
Zwecke.
Ich will aber auch den timeout() von LWP nutzen, der eben auf alarm() zugreift.
Da der Inhalt meines alarms nicht gerettet wird, wird der LWP-timeout mein alarm()
disablen, wenn nicht gar sinnlos machen.
Ich möchte ja die Timeout-Methode von LWP nutzen....aber gleichzeitig brauch ich
alarm() noch für andere Programmteile.
Ok, billige Lösung 1: Neues LWP installieren. Folge: Mein Kunde kriegt ne Krise :))
Lösung 2: LWP an dieser Stelle ändern und Inhalt des alarm()'s retten. Ist einfach zu machen, aber
auch dann mach ich LWP neu, hab keine Unterstuetzung und koennte eh gleich LWP neu installieren.
Lösung 3: Nicht LWP verwenden, sondern die Socket-Kommunikation selbst machen. Auch nicht schwer, aber
genauso sinnlos wie 2), da da nur das Rad neu erfunden wird und ne neue Insellösung gemacht.
Lösung 4: Ich ruf mit mein Handy die Uhrzeit-Auskunft der Teuerkom an, lege es direkt neben
mein Kopf und leg mich damit schlafen. Wenn ich aufwache hab ich meine Probleme
bestimmt vergessen :)
Lösung 5: (So hab ich es jetzt gemacht): timeout() auf FALSE und use_eval() auf FALSE. Dann steuer ich den inneren
Timeout (den des LWPs) garnicht mehr, aber kann durch meine andxeren Subroutinen doch
noch abbrechen, auch wenn eine URL bis ultimo brauchen könnte.
Hast du eine bessere Lösung?
Ciao,
Wolfgang
Lange Rede, kurzer Sinn: Hat jemand eine Ahnung, wie ich dies
umgehen kann, also sowohl alarm() in meinem Hauptprogramm,
als auch den von LWP gleichzeitig nutzen?
(Immer im Hinterkopf, das die Alarmzeit vom
Hauptprogramm != Timeout von LWP)
Brauchst Du unbedingt das interne "alarm()", oder nur dessen Wirkung? Und wie oft?
Läßt sich das Problem vielleicht durch "outsourcen" lösen? Also durch einen zweiten Prozeß, etwa ein shell-Skript, welches selbst ein sleep () und ein "kill -SIGirgendwas" an Dein Perl-Skript schickt?
Lange Rede, kurzer Sinn: Hat jemand eine Ahnung, wie ich dies
umgehen kann, also sowohl alarm() in meinem Hauptprogramm,
als auch den von LWP gleichzeitig nutzen?
(Immer im Hinterkopf, das die Alarmzeit vom
Hauptprogramm != Timeout von LWP)Brauchst Du unbedingt das interne "alarm()", oder nur dessen Wirkung? Und wie oft?
Läßt sich das Problem vielleicht durch "outsourcen" lösen? Also durch einen zweiten Prozeß, etwa ein shell-Skript, welches selbst ein sleep () und ein "kill -SIGirgendwas" an Dein Perl-Skript schickt?
Ich brauch das Alarm um einen Spidervorgang abzubrechen.
Und zwar nich nur abbrechen in Bezug auf die dauer einzelner Siteabgriffe,
sondern auch in Bezug auf das gesamte Programm, welches ebenfalls
nur eine bestimmte Zeit X laufen soll, egal wieviele URL's bisher erfolgreich
geschafft wurden oder nicht.
Desweiteren hab ich bereits Outgesourced, also
diese Prozeduren in externe Programme ausgelagert, da ich den Spider bereits ab bestimmten Menge an zu spiderden
Domains plitte, d.h. die AUfgabe an Kinderprozesse verteile.
Theoretisch koennte ich sicher nochmal dasselbe machen
(Am Anfang der Entwicklung hatte ich das auch schon mal gemacht),
aber dies hat wieder Probleme an anderer Stelle, weil ich neben
den zeitlich bedingten Timeouts, auch eine Abbruchbedingung fuer eine
bestimmte Gesamtuebertragungsmenge eingebaut habe.
Ich denke eigentlich diese Umbauten sind dann doch zu zeitaufwendig, d.h.
es ist schneller, mal eben alarm() oder LWP selbst anzupassen.....
Aber jetzt hab ich es so gemacht wie unten in der Re: auf Bjoern
beschrieben....
Mist! Irgentwie haette ich wirklich fast Lust mit Gisle bischen weiter
an LWP zu aendern, aber ich hab naechste WOche leider Urlaub :((
Ciao,
Wolfgang