Wolfgang Wiese: alarm() und LWP: timeout()

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

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

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

      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

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

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

  2. 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?

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