Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Signalhandler an Kindklasse vererben

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Signalhandler an Kindklasse vererben

    Hallo!

    Momentan spiele ich mit einigen Skripten, die irgendeine Art von Dienst bereitstellen und als daemon laufen sollen. Dazu habe ich eine allgemeine Klasse Service erstellt, die grundlegende Funktionen für alle Dienste bereitstellen soll. Sie ist hier zum einfacheren Verständnis stark vereinfacht.

    Service.php
    PHP-Code:
    <?php
    class Service {
        protected static 
    $PIDFile null;

        protected static function 
    init($serviceName_param) {
            
    self::$PIDFile $serviceName_param.".pid";
            
    // @TODO check if process not already started
     
            
    set_time_limit(0);
            declare(
    ticks 3);
            
            
    pcntl_signal(SIGCHLD'self::sigControl_handleSignals');
            
    pcntl_signal(SIGTERM'self::sigControl_handleSignals'); 
            
    pcntl_signal(SIGINT,  'self::sigControl_handleSignals');
            
            
    file_put_contents(self::$PIDFilegetmypid());
            
    register_shutdown_function("self::removePID");
        }
        
        protected static function 
    removePID() {
            
    unlink(self::$PIDFile);
        }

        protected static function 
    sigControl_handleSignals($signal_param) {
            echo 
    "WE GOT A SIGNAL: $signal_param";
        }
    }
    ?>
    Nun soll es beliebig viele Dienste (i.e. Kindklassen) geben, die von dieser Klasse erben.

    test.php
    PHP-Code:
    <?php
    require_once "Service.php";

    class 
    test extends Service {
        public static function 
    _start() {
            
    self::init("test");
            while(
    true) { sleep(2); }
        }
    }
    test::_start();
    ?>
    Nun das Problem: Wenn ich test.php ausführe, läuft der Prozess wie gewollt endlos in einer Schleife. Leider reagiert er aber überhaupt gar nicht auf Signale, obwohl der Code, in dem die Signalhandler zugewiesen werden, ausgeführt wird und pcntl_signal auch eine positive Rückgabe liefert.
    Hat jemand dafür eine Erklärung?

  • #2
    ich würde den service mal daemonizen.

    auf was für signale soll er nicht reagieren?

    was killst du wenn du killst die schleife/den sleep oder den parent?

    wilkommen im forum und:
    http://www.php.de/php-fortgeschritte...uncements.html

    Kommentar


    • #3
      Der Service ist normalerweise daemonized, das macht aber keinen Unterschied. Ich hab das hier rausgenommen, weil es einfacher zu testen ist. Ich starte also in einem Terminal mit php test.php das Skript und in einem anderen schaue ich mir mit ps a den Zustand an oder sende mit kill Signale.
      Das Skript sollte sowohl auf SIGTERM als auch auf SIGINT reagieren (Strg+C in PHP-Terminal bzw. kill PID im Kontrollterminal). Tut es aber leider nicht; jedenfalls wird die Funktion sigControl_handleSignals nicht ausgeführt. Ansonsten ist das für mich eine ziemliche Blackbox. Ich weiß aber, dass die Ursache im geposteten Code liegen muss, denn an anderen Stellen, wo ich es außerhalb von Objekten verwende, funktioniert es.

      was killst du wenn du killst die schleife/den sleep oder den parent?
      Wie meinst du das? Kill bezieht sich auf den Prozess als Ganzes, nicht auf einen Teil des Programms.

      Kommentar


      • #4
        Versuch mal
        PHP-Code:
        {'Service''sigControl_handleSignals'
        oder
        PHP-Code:
        'Service::sigControl_handleSignals' 
        als Callback.
        [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

        Kommentar


        • #5
          Code:
          declare(ticks = 3);
          Wieso 3?

          Wieso in der Methode? Soweit ich weiß gilt das immer nur dateiweit oder im angegeben {}-Block (wie bei Namespaces).

          Evtl. auch mal pcntl_signal_dispatch anschauen.

          Grüße.

          Kommentar


          • #6
            PHP-Code:
            pcntl_signal(SIGCHLD, {'Service''sigControl_handleSignals'}); 
            gibt einen Syntax-Error und
            PHP-Code:
            'Service::sigControl_handleSignals' 
            hat leider denselben Effekt wie mit self.

            Die ticks habe ich auf 3 gesetzt, weil das die Ausführung beschleunigt (sonst wird sozusagen die dispatch-Methode nach jedem Statement ausgeführt, so nur nach jedem dritten).

            Soweit ich weiß gilt das immer nur dateiweit oder im angegeben {}-Block (wie bei Namespaces).
            Das überrascht mich, wäre aber ja eine Erklärung. Ich teste das mal…

            EDIT: Tatsächlich! Wenn ich die Schleife in derselben Methode laufen lasse, in der auch die Signalhandler installiert wurden, funktioniert es. Also mache ich das jetzt außerhalb der Klasse, dann müsste es ja funktionieren.

            Danke =D!

            Kommentar


            • #7
              E: Ich hab PHP verlernt...
              [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

              Kommentar


              • #8
                PHP-Code:
                {'Service''sigControl_handleSignals'} ---> ['Service''sigControl_handleSignals'
                Grüße.

                Kommentar


                • #9
                  PHP ist auf 5.5.9, das ist die aktuellste Version in den Standard-Paketquellen (ich nutze Ubuntu).

                  pcntl_signal_dispatch ist eine wirklich feine Sache! Da kann ich die Signalhandler sogar in der Methode lassen und außerdem den Zeitpunkt selbst bestimmen, an dem ein Abbrechen möglich ist, was ich vorher nur umständlich über eine delay_exit-Klassenvariable machen konnte, die sich dann merken musste, ob man gerade Abbrechen kann oder nicht und wenn nicht, ob denn zwischenzeitlich ein Signal reingekommen ist blablabla… Das ist so viel angenehmer.

                  Kommentar


                  • #10
                    Die ticks habe ich auf 3 gesetzt, weil das die Ausführung beschleunigt (sonst wird sozusagen die dispatch-Methode nach jedem Statement ausgeführt, so nur nach jedem dritten).
                    Wie schon erwähnt, schau dir pcntl_signal_dispatch an. Dann kannst du selbst steuern wann die Signale verarbeitet werden.

                    Grüße.

                    @edit: das kam nun irgendwie zeitgleich ^^

                    Kommentar


                    • #11
                      Zitat von php1704 Beitrag anzeigen
                      PHP-Code:
                      {'Service''sigControl_handleSignals'} ---> ['Service''sigControl_handleSignals'
                      Grüße.
                      So klappt's bei mir auch =).

                      Kommentar

                      Lädt...
                      X