Start · Sprachen · PHP · Referenz · pcntl_waitpid

pcntl_waitpid

Funktion

Wartet auf ein abgezweigtes Kind-Prozess oder gibt dessen Status zurück, um Zombie-Prozesse zu vermeiden.

seit PHP 4.1.0 Kategorie: misc

Signatur

pcntl_waitpid(int $process_id, int &$status, int $flags = 0, array &$resource_usage = []): int

Beschreibung

pcntl_waitpid() hält den aktuellen Prozess an, bis der durch $process_id angegebene Kind-Prozess beendet wird, oder gibt sofort zurück, falls der Kind-Prozess bereits beendet ist. Diese Funktion ist essenziell, um sogenannte Zombie-Prozesse zu vermeiden: Wenn ein Eltern-Prozess nicht auf seine Kinder wartet, bleiben deren Prozesseinträge im System erhalten, bis der Eltern-Prozess selbst endet.

Der Parameter $process_id steuert, auf welche Kinder gewartet wird: Ein Wert von -1 wartet auf beliebige Kinder (wie pcntl_wait()), ein positiver Wert wartet auf genau den Kind-Prozess mit dieser PID, 0 wartet auf ein Kind in derselben Prozessgruppe, und ein Wert kleiner als -1 wartet auf Kinder mit der Prozessgruppen-ID gleich dem Absolutwert.

Über den $flags-Parameter lässt sich das Verhalten anpassen: Mit WNOHANG kehrt die Funktion sofort zurück, wenn kein Kind beendet wurde (nicht-blockierendes Warten). WUNTRACED liefert auch Statusinformationen über gestoppte Kinder. Der zurückgegebene $status kann anschließend mit Funktionen wie pcntl_wexitstatus(), pcntl_wifexited() oder pcntl_wifsignaled() ausgewertet werden.

Die Funktion ist besonders in Daemon-Prozessen, Worker-Pools und parallelen Verarbeitungs-Szenarien nützlich, in denen mehrere Kind-Prozesse erzeugt und sauber überwacht werden müssen.

Parameter

Name Typ Default Beschreibung
$process_id Pflicht int PID des zu erwartenden Kind-Prozesses. -1 = beliebiger Kind-Prozess, 0 = Kinder in derselben Prozessgruppe, positiver Wert = exakte PID, negativer Wert < -1 = Kinder mit Prozessgruppen-ID gleich dem Absolutwert.
$status Pflicht int Wird per Referenz übergeben und enthält nach dem Aufruf den Statuscode des Kind-Prozesses. Kann mit pcntl_wifexited(), pcntl_wexitstatus(), pcntl_wifsignaled() usw. ausgewertet werden.
$flags int 0 Steuerungsflags als Bitmask. WNOHANG: Sofortiger Rückgabe wenn kein Kind beendet wurde. WUNTRACED: Liefert auch Status von gestoppten Kindprozessen.
$resource_usage array [] Wird per Referenz übergeben und enthält nach dem Aufruf Ressourcenverbrauch-Informationen des beendeten Kind-Prozesses (ab PHP 8.1 verfügbar).

Rückgabewert

Typ
int
Beschreibung
Gibt die PID des beendeten Kind-Prozesses zurück, bei einem Fehler -1, oder 0 wenn WNOHANG gesetzt ist und kein Kind beendet wurde.

Beispiele

Einfaches Warten auf einen Kind-Prozess

<?php
$pid = pcntl_fork();

if ($pid === -1) {
    die('Fork fehlgeschlagen');
} elseif ($pid === 0) {
    // Kind-Prozess
    echo "Kind-Prozess läuft (PID: " . posix_getpid() . ")\n";
    sleep(1);
    exit(42); // Exit-Code 42
} else {
    // Eltern-Prozess wartet auf das Kind
    $childPid = pcntl_waitpid($pid, $status);

    if (pcntl_wifexited($status)) {
        $exitCode = pcntl_wexitstatus($status);
        echo "Kind-Prozess (PID: $childPid) beendet mit Exit-Code: $exitCode\n";
    }
}
Kind-Prozess läuft (PID: 1234) Kind-Prozess (PID: 1234) beendet mit Exit-Code: 42

Nicht-blockierendes Warten mit WNOHANG (Worker-Pool)

<?php
$workers = [];

// 3 Worker-Prozesse starten
for ($i = 0; $i < 3; $i++) {
    $pid = pcntl_fork();
    if ($pid === -1) {
        die('Fork fehlgeschlagen');
    } elseif ($pid === 0) {
        // Kind-Prozess: Arbeit simulieren
        sleep(rand(1, 3));
        exit(0);
    } else {
        $workers[$pid] = true;
        echo "Worker gestartet mit PID: $pid\n";
    }
}

// Nicht-blockierend auf beendete Worker prüfen
while (!empty($workers)) {
    foreach (array_keys($workers) as $workerPid) {
        $result = pcntl_waitpid($workerPid, $status, WNOHANG);
        if ($result > 0) {
            echo "Worker $workerPid beendet.\n";
            unset($workers[$workerPid]);
        } elseif ($result === -1) {
            echo "Fehler beim Warten auf Worker $workerPid\n";
            unset($workers[$workerPid]);
        }
    }
    usleep(100000); // 100ms warten vor nächster Prüfung
}

echo "Alle Worker beendet.\n";
Worker gestartet mit PID: 1235 Worker gestartet mit PID: 1236 Worker gestartet mit PID: 1237 Worker 1236 beendet. Worker 1235 beendet. Worker 1237 beendet. Alle Worker beendet.

// Wichtig · Fallstricke

Wichtig: pcntl_waitpid() steht nur auf Unix-ähnlichen Systemen (Linux, macOS) zur Verfügung und ist unter Windows nicht nutzbar. Die PHP-Erweiterung pcntl muss aktiviert sein.

Zombie-Prozesse: Wird diese Funktion (oder pcntl_wait()) nicht aufgerufen, bleiben beendete Kind-Prozesse als Zombie in der Prozesstabelle, bis der Eltern-Prozess endet. In langlebigen Daemon-Prozessen kann dies zur Erschöpfung der Prozessslots führen.

Signal-Handler: In Anwendungen mit Signal-Handling empfiehlt es sich, pcntl_waitpid() im SIGCHLD-Handler mit WNOHANG aufzurufen, um beendete Kinder asynchron aufzuräumen. Dabei sollte die Schleife so lange laufen, bis der Rückgabewert 0 oder -1 ist, um alle bereits beendeten Kinder zu erfassen.