Start · Sprachen · PHP · Referenz · pcntl_waitid

pcntl_waitid

Funktion

Wartet auf eine Zustandsänderung eines Kindprozesses und gibt detaillierte Statusinformationen zurück.

seit PHP 8.3.0 Kategorie: misc

Signatur

pcntl_waitid(int $idtype = P_ALL, int $id = 0, array &$info = [], int $flags = WEXITED): bool

Beschreibung

pcntl_waitid() ist eine POSIX-konforme Funktion, die auf eine Zustandsänderung eines oder mehrerer Kindprozesse wartet. Im Gegensatz zu pcntl_wait() und pcntl_waitpid() bietet sie eine feinere Steuerung darüber, welche Kindprozesse überwacht werden sollen, und liefert detailliertere Statusinformationen über das $info-Array.

Der Parameter $idtype bestimmt den Typ der zu überwachenden Prozess-ID: P_ALL überwacht alle Kindprozesse, P_PID einen bestimmten Prozess anhand seiner PID und P_PGID alle Prozesse einer bestimmten Prozessgruppe. Der Parameter $flags erlaubt es, das Verhalten der Funktion zu steuern, z. B. ob blockiert wird (WNOHANG verhindert das Blockieren) oder ob auch gestoppte/fortgesetzte Prozesse berücksichtigt werden (WSTOPPED, WCONTINUED).

Das Referenz-Array $info wird nach dem Aufruf mit POSIX-siginfo_t-ähnlichen Feldern befüllt, darunter si_pid (PID des Kindprozesses), si_uid (UID), si_signo (Signal), si_status (Exit-Status oder Signal) und si_code (Ursachencode wie CLD_EXITED, CLD_KILLED etc.).

Diese Funktion ist besonders nützlich für Server- und Daemon-Anwendungen, die mehrere Kindprozesse verwalten und auf deren Lebenszyklusereignisse detailliert reagieren müssen. Sie steht nur auf POSIX-konformen Systemen (Linux, macOS, BSD) zur Verfügung; auf Windows ist sie nicht verfügbar.

Parameter

Name Typ Default Beschreibung
$idtype int P_ALL Typ der Prozess-ID, die überwacht werden soll. Mögliche Werte: P_ALL (alle Kindprozesse), P_PID (Prozess mit der in $id angegebenen PID), P_PGID (alle Prozesse der in $id angegebenen Prozessgruppe).
$id int 0 Die Prozess-ID oder Prozessgruppen-ID, die in Kombination mit $idtype ausgewertet wird. Wird bei P_ALL ignoriert.
$info array [] Wird als Referenz übergeben und nach dem Aufruf mit Informationen über den Kindprozess befüllt. Enthält Felder wie si_pid, si_uid, si_signo, si_status und si_code.
$flags int WEXITED Steuert das Verhalten der Funktion. Kombinierbare Konstanten: WEXITED (auf beendete Prozesse warten), WNOHANG (nicht blockieren), WSTOPPED (auf gestoppte Prozesse reagieren), WCONTINUED (auf fortgesetzte Prozesse reagieren), WNOWAIT (Prozess im wartenden Zustand belassen).

Rückgabewert

Typ
bool
Beschreibung
Gibt true zurück, wenn die Funktion erfolgreich auf eine Zustandsänderung gewartet hat. Gibt false zurück, wenn ein Fehler aufgetreten ist oder bei WNOHANG kein Kindprozess sofort verfügbar war. Im Fehlerfall kann pcntl_get_last_error() zur Fehlerdiagnose verwendet werden.

Beispiele

Auf das Ende eines bestimmten Kindprozesses warten

<?php
$pid = pcntl_fork();

if ($pid === -1) {
    die('Fork fehlgeschlagen');
} elseif ($pid === 0) {
    // Kindprozess
    echo "Kindprozess (PID: " . posix_getpid() . ") läuft...\n";
    sleep(1);
    exit(42);
} else {
    // Elternprozess
    $info = [];
    $result = pcntl_waitid(P_PID, $pid, $info, WEXITED);

    if ($result) {
        echo "Kindprozess beendet:\n";
        echo "  PID:       " . $info['si_pid'] . "\n";
        echo "  Exit-Code: " . $info['si_status'] . "\n";
        echo "  Ursache:   " . $info['si_code'] . " (CLD_EXITED = " . CLD_EXITED . ")\n";
    } else {
        echo "Fehler: " . pcntl_strerror(pcntl_get_last_error()) . "\n";
    }
}
Kindprozess (PID: 12346) läuft... Kindprozess beendet: PID: 12346 Exit-Code: 42 Ursache: 1 (CLD_EXITED = 1)

Nicht-blockierendes Überwachen aller Kindprozesse mit WNOHANG

<?php
$kinder = [];

for ($i = 0; $i < 3; $i++) {
    $pid = pcntl_fork();
    if ($pid === 0) {
        sleep(rand(1, 3));
        exit($i * 10);
    }
    $kinder[] = $pid;
}

// Elternprozess wartet nicht-blockierend auf alle Kinder
$beendet = [];
while (count($beendet) < count($kinder)) {
    $info = [];
    $result = pcntl_waitid(P_ALL, 0, $info, WEXITED | WNOHANG);

    if ($result && isset($info['si_pid']) && $info['si_pid'] > 0) {
        $beendet[] = $info['si_pid'];
        echo "Kind " . $info['si_pid'] . " beendet mit Status " . $info['si_status'] . "\n";
    } else {
        // Kurz warten, damit die CPU nicht vollständig belastet wird
        usleep(100000);
    }
}
echo "Alle Kindprozesse beendet.\n";
Kind 12347 beendet mit Status 0 Kind 12348 beendet mit Status 10 Kind 12349 beendet mit Status 20 Alle Kindprozesse beendet.

// Wichtig · Fallstricke

Plattformverfügbarkeit: pcntl_waitid() ist nur auf POSIX-konformen Systemen (Linux, macOS, BSD) verfügbar, die die zugrunde liegende waitid()-Systemfunktion unterstützen. Auf Windows-Systemen existiert diese Funktion nicht.

Zombie-Prozesse: Wenn Kindprozesse enden, ohne dass der Elternprozess auf sie wartet, entstehen sogenannte Zombie-Prozesse. pcntl_waitid() bereinigt diese durch das Einsammeln des Exit-Status. Bei WNOWAIT bleibt der Prozess hingegen im Zombie-Zustand, bis er erneut abgewartet wird.

Signal-Handler: In Anwendungen, die SIGCHLD-Handler verwenden, sollte pcntl_waitid() mit WNOHANG innerhalb des Handlers aufgerufen werden, um Race Conditions zu vermeiden.

Fehlerbehandlung: Bei einem Fehler (Rückgabe false) kann der Fehlercode über pcntl_get_last_error() und der Fehlertext über pcntl_strerror() ermittelt werden. Der häufige Fehlercode ECHILD bedeutet, dass keine passenden Kindprozesse vorhanden sind.