Start · Sprachen · PHP · Referenz · EvFork

EvFork

Klasse

Ein <code>EvFork</code>-Watcher wird ausgelöst, sobald der <code>ev</code>-Event-Loop nach einem <code>fork()</code>-Systemaufruf neu gestartet wird.

Kategorie: io

Signatur

class EvFork extends EvWatcher

Beschreibung

EvFork ist ein spezieller Watcher der ev-Erweiterung (PECL), der immer dann aktiviert wird, wenn der laufende Prozess eine fork()-Operation durchgeführt hat und der Event-Loop im Kindprozess zum ersten Mal iteriert. Dies ist notwendig, weil viele interne Zustände eines Event-Loops – beispielsweise offene Dateideskriptoren, epoll- oder kqueue-Handles – nach einem fork() im Kindprozess ungültig sind.

Mit einem EvFork-Watcher kann der Entwickler den Event-Loop und damit verbundene Ressourcen im Kindprozess sauber zurücksetzen oder neu initialisieren, bevor der erste reguläre Event-Callback ausgeführt wird. Typische Anwendungen sind das Neuinitialisieren von Datenbankverbindungen, das Schließen von Sockets, die nur dem Elternprozess gehören, oder das Neustarten von Hintergrundthreads.

Die Klasse erbt von EvWatcher und bietet dieselben Steuerungsmethoden (start(), stop(), keepalive() usw.). Im Gegensatz zu anderen Watchern hat EvFork keinen eigenen Beobachtungswert – es gibt keine Datei, keinen Timer oder kein Signal; der einzige Auslöser ist der Post-Fork-Zustand des Loops.

Zu beachten ist, dass EvFork-Callbacks nur im Kindprozess ausgelöst werden und der Elternprozess davon nicht betroffen ist. Das Zurücksetzen des Loops im Kindprozess sollte über EvLoop::defaultLoop() oder die jeweilige Loop-Instanz erfolgen.

Parameter

Name Typ Default Beschreibung
$callback Pflicht callable Eine aufrufbare Funktion, die nach dem fork() im Kindprozess beim ersten Loop-Durchlauf aufgerufen wird. Signatur: function(EvFork $watcher, int $revents): void.
$data mixed null Beliebige benutzerdefinierte Daten, die dem Watcher zugeordnet werden und über $watcher->data zugänglich sind.
$priority int 0 Priorität des Watchers. Höhere Werte bedeuten frühere Ausführung innerhalb desselben Loop-Durchlaufs. Gültige Werte: Ev::MINPRI bis Ev::MAXPRI.

Beispiele

Datenbankverbindung nach fork() neu initialisieren

<?php
// Voraussetzung: PECL-Erweiterung 'ev' ist installiert

$forkWatcher = new EvFork(
    function (EvFork $watcher, int $revents): void {
        // Dieser Code läuft nur im Kindprozess nach fork()
        echo "[Kind PID " . posix_getpid() . "] fork() erkannt – Loop und Ressourcen werden neu initialisiert.\n";

        // Beispiel: Datenbankverbindung trennen und neu aufbauen
        // $db->close();
        // $db->connect();

        // Loop-Zustand im Kindprozess zurücksetzen
        Ev::defaultLoop();
    },
    null,     // keine benutzerdefinierten Daten
    Ev::MAXPRI // höchste Priorität, damit es zuerst läuft
);

$pid = pcntl_fork();
if ($pid === 0) {
    // Kindprozess: Event-Loop starten
    Ev::run(Ev::RUN_ONCE);
    exit(0);
} else {
    // Elternprozess: auf Kind warten
    pcntl_waitpid($pid, $status);
    echo "[Eltern PID " . posix_getpid() . "] Kindprozess beendet.\n";
}
[Kind PID 12346] fork() erkannt – Loop und Ressourcen werden neu initialisiert. [Eltern PID 12345] Kindprozess beendet.

EvFork mit einer eigenen Loop-Instanz verwenden

<?php
// Eigene Loop-Instanz (nicht den Default-Loop)
$loop = new EvLoop();

$forkWatcher = $loop->fork(
    function (EvFork $watcher, int $revents) use ($loop): void {
        echo "Kindprozess PID: " . posix_getpid() . " – eigene Loop-Instanz zurücksetzen.\n";
        // Hier können loop-spezifische Ressourcen zurückgesetzt werden
        $watcher->stop(); // Watcher deaktivieren, wenn er nur einmalig benötigt wird
    }
);

$pid = pcntl_fork();
if ($pid === 0) {
    $loop->run(Ev::RUN_ONCE);
    exit(0);
}
pcntl_waitpid($pid, $status);
Kindprozess PID: 12347 – eigene Loop-Instanz zurückgesetzt.

// Wichtig · Fallstricke

Wichtig: EvFork-Watcher werden ausschließlich im Kindprozess ausgelöst. Der Elternprozess empfängt kein Ereignis. Nach einem fork() sollte man im Kindprozess immer alle Ressourcen neu initialisieren, die nicht fork-sicher sind (z. B. Datenbankverbindungen, Mutex-Handles, Netzwerk-Sockets).

Ressourcenkonflikt: Ohne EvFork-Handler können im Kindprozess Doppelschreibungen auf Sockets oder Datenbankverbindungs-Korruptionen auftreten, da Eltern- und Kindprozess dieselben Dateideskriptoren teilen.

Abhängigkeit: Die Klasse steht nur zur Verfügung, wenn die PECL-Erweiterung ev installiert ist (pecl install ev). Sie ist nicht Teil der PHP-Standardinstallation.