Start · Sprachen · PHP · Referenz · EvSignal

EvSignal

Klasse

Überwacht ein Unix-Signal und ruft beim Empfang des Signals einen Callback auf.

seit PHP 0.2.0 Kategorie: io

Signatur

class EvSignal extends EvWatcher

Beschreibung

EvSignal ist ein Watcher der Ev-Erweiterung, der einen Callback ausführt, sobald ein bestimmtes Unix-Signal (z. B. SIGTERM, SIGHUP, SIGUSR1) an den aktuellen Prozess gesendet wird. Er eignet sich hervorragend für saubers Prozess-Management in lang laufenden PHP-Prozessen wie Daemons oder Queue-Workern.

Im Gegensatz zu den nativen PHP-Funktionen pcntl_signal() und pcntl_signal_dispatch() basiert EvSignal auf der libev-Ereignisschleife und ermöglicht so eine vollständig nicht-blockierende, ereignisgesteuerte Signal-Behandlung ohne manuelles Polling. Der Watcher wird in die Ev-Ereignisschleife eingebunden und feuert, sobald ein Signal eintrifft.

Ein typischer Anwendungsfall ist das Abfangen von SIGTERM oder SIGINT, um einen Daemon kontrolliert herunterzufahren, oder das Reagieren auf SIGHUP, um Konfigurationsdateien neu zu laden. Mehrere EvSignal-Watcher für dasselbe Signal können gleichzeitig existieren und werden alle benachrichtigt.

Beachte: Die Ev-Erweiterung muss über PECL installiert sein. Signal-Watcher funktionieren nur auf Unix-ähnlichen Betriebssystemen; unter Windows sind sie nicht verfügbar.

Parameter

Name Typ Default Beschreibung
$signum Pflicht int Die Signalnummer, die überwacht werden soll. Kann eine Konstante wie SIGTERM, SIGHUP, SIGUSR1 usw. sein.
$callback Pflicht callable Der Callback, der aufgerufen wird, wenn das Signal empfangen wurde. Signatur: function(EvSignal $watcher, int $revents): void.
$data mixed null Beliebige Benutzerdaten, die dem Watcher zugeordnet werden und über $watcher->data abrufbar sind.
$priority int 0 Priorität des Watchers. Höhere Werte bedeuten frühere Ausführung. Gültige Werte: Ev::MINPRI bis Ev::MAXPRI.

Beispiele

SIGTERM abfangen und Daemon sauber beenden

<?php
// Reagiert auf SIGTERM und beendet die Ereignisschleife sauber
$signalWatcher = new EvSignal(SIGTERM, function (EvSignal $watcher, int $revents) {
    echo "SIGTERM empfangen – fahre Daemon herunter..." . PHP_EOL;
    // Ressourcen freigeben, Verbindungen schließen usw.
    $watcher->stop();
    Ev::stop(Ev::BREAK_ALL);
});

echo "Daemon läuft. PID: " . getmypid() . PHP_EOL;
// Startet die Ereignisschleife (blockiert, bis Ev::stop() aufgerufen wird)
Ev::run();
Daemon läuft. PID: 12345 SIGTERM empfangen – fahre Daemon herunter...

SIGHUP zum Neuladen der Konfiguration und SIGUSR1 für Status-Dump nutzen

<?php
$config = ['debug' => false];

// Konfiguration bei SIGHUP neu laden
$sighupWatcher = new EvSignal(SIGHUP, function () use (&$config) {
    echo "SIGHUP empfangen – lade Konfiguration neu..." . PHP_EOL;
    // Simuliertes Neuladen
    $config['debug'] = !$config['debug'];
    echo "Debug-Modus ist jetzt: " . ($config['debug'] ? 'AN' : 'AUS') . PHP_EOL;
});

// Status-Dump bei SIGUSR1
$sigusr1Watcher = new EvSignal(SIGUSR1, function () use (&$config) {
    echo "Status-Dump:" . PHP_EOL;
    print_r($config);
});

// Timer, der nach 10 Sekunden automatisch stoppt (für das Beispiel)
$timer = new EvTimer(10, 0, function () {
    Ev::stop(Ev::BREAK_ALL);
});

echo "Warte auf Signale (PID: " . getmypid() . ")..." . PHP_EOL;
Ev::run();
Warte auf Signale (PID: 12345)...

// Wichtig · Fallstricke

Nur Unix: Signal-Watcher funktionieren ausschließlich auf Unix-ähnlichen Systemen (Linux, macOS, BSD). Unter Windows sind Unix-Signale nicht verfügbar und der Einsatz von EvSignal schlägt fehl.

Kompatibilität mit pcntl: EvSignal und pcntl_signal() sollten nicht gleichzeitig für dasselbe Signal verwendet werden, da sie sich gegenseitig überschreiben können. Wähle eine Methode für die Signal-Behandlung.

PECL-Abhängigkeit: Die Ev-Erweiterung ist keine Standard-PHP-Erweiterung und muss separat über PECL installiert werden: pecl install ev. Stelle sicher, dass extension=ev.so in der php.ini eingetragen ist.

Signal-Sicherheit: Im Callback sollten möglichst nur async-signal-safe Operationen ausgeführt werden. libev puffert Signale intern sicher, sodass der Callback tatsächlich in der normalen Ereignisschleife ausgeführt wird und nicht direkt im Signal-Handler-Kontext.