wait(2)

NAAM
wait, waitpid, waitid - wacht op toestand verandering in een proces

BIBLIOTHEEK
Standaard C bibliotheek (libc, -lc)

SAMENVATTING
#include <sys/wait.h>

pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *_NULL_baarwstatus, int opties);

int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
                /* This is the glibc and POSIX interface; see
                   VERSIONS for information on the raw system call.  */

    Feature Test Macro Requirements voor glibc (zie feature_test_macros(7)):

waitid():
    Vanaf glibc 2.26:
        _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L
    glibc 2.25 en eerder:
        _XOPEN_SOURCE
            || /* Vanaf glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
            || /* Glibc <= 2.19: */ _BSD_SOURCE

BESCHRIJVING
Al deze systeem aanroepen worden gebruikt om te wachten op een toestandsverandering in een kind van het aanroepende proces en verkrijgen informatie over het kind wiens toestand werd veranderd. Een toestandsverandering wordt gezien als: het kind werd beëindigd; het kind werd beëindigd door een signaal; of het kind werd hervat door een signaal. In het geval van een beëindigd kind, het uitvoeren van een "wacht" maakt het mogelijk dat het systeem de hulpbronnen die geassocieerd zijn met het kind kunnen vrijgeven; als de "wacht" niet wordt uitgevoerd, dan blijft het beëindigde kind een een "zombie" toestand (zie OPMERKINGEN hieronder).

Als een kind al van toestand is veranderd, dan keren deze aanroepen meteen terug. Anders zouden ze blokkeren totdat een kind van toestand verandert of een signaal verwerker interrumpeert de aanroep (aannemende dat systeem aanroepen niet automatisch geherstart worden gebruik makende van de SA_RESTART vlag van sigaction(2)). In de rest van deze pagina:een kind waarvan de toestand werd veranderd en waarop niet gewacht werd door een van de systeem aanroepen wordt aangeduid als waitable.

  wait() and waitpid()
De wait() systeem aanroep schort het uitvoeren van de huidige thread op totdat een van zijn kinderen eindigt. De aanroep wait(&wstatus) is equivalent aan:

    waitpid(-1, &wstatus, 0);

De waitpid() systeem aanroep schort het uitvoeren van de huidige thread op tot dat een kind gespecificeerd door pid argument is veranderd van toestand. Standaard wacht waitpid() alleen op beëindigde kinderen, maar is dit gedrag aanpasbaar via het opties argument, zoals hieronder beschreven.

De waarde van pid kan een van de volgende zijn:

< -1
    wat betekend dat er gewacht wordt op elk kind proces van wie de proces groep ID gelijk is aan de absolute waarde van pid.

-1  wat betekent wacht op een kind proces.

0   wat betekend dat er gewacht wordt op elk kind proces van wie het proces groep ID gelijk is aan dat van het aanroepende proces ten tijde van de aanroep van waitpid().

> 0 wat betekend dat er gewacht wordt op elk kind van wie het proces ID gelijk is aan de waarde van pid.

De waarde van opties is een OF (incl.) van nul of meer van de volgende constanten:

WNOHANG
    betekend dat er onmiddellijk wordt teruggekeerd als geen kind beëindigd was.

WUNTRACED
    keer ook terug als het kind werd beëindigd (maar niet getraceerd via ptrace(2)). In de status van traced kinderen die werden beëindigd wordt voorzien, zelfs als deze optie niet werd opgegeven.

WCONTINUED (sinds Linux 2.6.10)
    keer ook terug als een beëindigd kind werd hervat door het afleveren van SIGCONT.

(Zie hieronder voor de alleen-Linux opties.)

Als wstatus niet NULL is, dan slaan wait() en waitpid() status informatie op in de int naar welk het wijst. Dit geheel getal kan worden ingezien met de volgende macro´s (die het geheel getal zelf als argument gebruiken, niet de wijzer er naar toe, zoals gedaan in wait() en waitpid()!):

WIFEXITED(wstatus)
    retourneert "waar" als het kind normaal beëindigde, dat is, door het aanroepen van exit(3) of _exit(2), of door terug te keren uit main().

WEXITSTATUS(wstatus)
    retourneert de terugkeer status van het kind. Deze bestaat uit de minst belangrijke 8 bits van het status argument dat het kind specificeerde in een aanroep van exit(3) of _exit(2) of als het argument van een return statement in main(). Deze macro moet alleen gebruikt worden als WIFEXITED een "waar" terug gaf.

WIFSIGNALED(wstatus)
    geeft "waar" terug als het proces eindigde door een signaal.

WTERMSIG(wstatus)
    geeft het nummer van het signaal dat ervoor zorgde dat het kind proces eindigde. Deze macro kan alleen gebruikt worden als WIFSIGNALED "waar" terug gaf.

WCOREDUMP(wstatus)  // POSIX.1-2024
    retourneert "waar" als het kind een core dump produceerde (zie core(5)). Deze macro kan alleen gebruikt worden als WIFSIGNALED "waar" terug gaf.

WIFSTOPPED(wstatus)  // POSIX.1-2024
    geeft "waar" terug als het kind proces werd beëindigd door het afleveren van een signaal; dit is alleen mogelijk als de aanroep werd gedaan met WUNTRACED of wanneer het kinderen wordt getraceerd (zie ptrace(2)).

WSTOPSIG(wstatus)
    geeft het nummer van het signaal dat ervoor zorgde dat het kind stopte. Deze macro kan alleen afgehandeld worden als WIFSTOPPED ongelijk-nul teruggaf.

WIFCONTINUED(wstatus)
    (vanaf Linux 2.6.10) geeft "waar" terug als het kind werd hervat door het aanleveren van SIGCONT.

  waitid()
De waitid() systeem aanroep (beschikbaar vanaf Linux 2.6.9.) geeft preciezere controle over het wachten op toestandsveranderingen van kinderen

De idtype en id argumenten selecteren de kind(eren) om op te wachten, als volgt:

idtype == P_PID
    Wacht op het kind wiens proces ID overeenkomt met id.

idtype == P_PIDFD (vanaf Linux 5.4)
    Wacht op het kind gerefereerd door de PID bestands beschrijving gespecificeerd in id. (Zie pidfd_open(2) voor verdere informatie over PID bestands beschrijvers.)

idtype == P_PGID
    Wacht op enig kind wiens proces groep ID overeenkomt met id. Vanaf Linux 5.4, als id is NUL, dan wacht op enig kind dat tot dezelfde proces groep zit als de proces groep van de aanroeper ten tijde van de aanroep.

idtype == P_ALL
    Wacht op enig kind; id wordt geïgnoreerd.

De kind status veranderingen om te wachten worden gespecificeerd door OF´en van een of meer van de volgende vlaggen in opties:

WEXITED
    Wacht op kinderen die zijn beëindigd.

WSTOPPED
    Wacht op kinderen die zijn gestopt door het leveren van een signaal.

WCONTINUED
    Wacht op (eerder gestopte) kinderen die zijn hervat door het aanleveren van SIGCONT.

De volgende vlaggen mogen additioneel worden geOF´d in opties:

WNOHANG
    Zoals voor waitpid().

WNOWAIT
    Laat het kind in een wachtbare status; een latere "wait"-aanroep kan opnieuw gebruikt worden om de status van het kind op te vragen.

Bij een succesvolle terugkeer, waitid() vult de volgende velden van de siginfo_t structure aangewezen door infop:

si_pid
    Het proces ID van het kind.

si_uid
    Het effectieve gebruiker ID van het kind. (Dit veld is niet gezet op de meeste andere implementaties.)

si_signo
    Altijd gezet op SIGCHLD.

si_status
    Ofwel de retour status van het kind, zoals mee gegeven aan _exit(2) (of exit(3)), ofwel het signaal de veroorzaakte het kind te beëindigen, stoppen of doorgaan. Het si_code veld kan worden gebruikt om te bepalen hoe dit veld te interpreteren.

si_code
    Zet op een van: CLD_EXITED (kind roep aan _exit(2)); CLD_KILLED (kind beëindigd door signaal); CLD_DUMPED (kind beëindigd door signaal, en dumpte core); CLD_STOPPED (kind gestopt door signaal); CLD_TRAPPED (getraceerd kind zit vast); or CLD_CONTINUED (kind vervolgt door SIGCONT).

Als WNOHANG werd opgegeven in opties en er waren geen kinderen in een wacht toestand, dan geeft waitid() meteen 0 terug and de status van de siginfo_t structure aangewezen door infop hangt af van de implementatie. Om (overdraagbaar) dit geval te onderscheiden van die waar een kind zich in een wacht toestand bevond, maak dan het si_pid veld nul voor de aanroep en controleer op een niet-nul waarde in dit veld nadat de aanroep terugkeerde.

POSIX.1-2008 Technical Corrigendum 1 (2013) voegt de eis toe dat wanneer WNOHANG werd gespecificeerd in opties en er waren geen kinderen wacht toestand, dan zou waitid() de si_pid en si_signo velden nul moeten maken. Op Linux en andere implementaties die aan deze eis voldoen, is het niet noodzakelijk om het si_pid veld nul te maken voor het aanroepen van waitid(). Echter volgen niet alle implementaties de POSIX.1 specificatie op dit punt.

EIND WAARDE
wait(): bij succes, retourneert het proces ID van het beëindigde kind; bij falen wordt een -1 teruggegeven.

waitpid(): bij succes, retourneert het proces ID van het kind waarvan de status werd veranderd; als WNOHANG gebruikt werd en een of meer kind(eren) aangeduid door pid bestaan, maar hebben hun toestand niet verandert, dan wordt nul teruggegeven. Bij een fout wordt -1 teruggegeven.

waitpid(): geeft 0 terug bij succes of als WNOHANG werd opgegeven en geen kind(eren) aangeduid door id is nog niet van toestand veranderd; bij een fout wordt -1 teruggegeven.

Bij falen, zal elk van deze aanroepen errno zetten om de fout aan te duiden.

FOUTEN

EAGAIN
    De PID bestandsindicator gespecificeerd in id is niet-blokkerend en het proces dat er naar verwijst werd niet beëindigd.

ECHILD
    (voor wait()) Het aanroepende proces heeft geen enkel kind waarop gewacht wordt.

ECHILD
    (voor waitpid() of waitid()) Het proces gespecificeerd door pid (waitpid()) of idtype en id (waitid()) bestaat niet of is geen kind van het aanroepende proces. (Dit kan gebeuren als het eigen kind als de actie voor SIGCHLD is gezet op SIG_IGN. Zie ook de Linux Opmerkingen sectie over threads.)

EINTR
    WNOHANG was is niet gezet en een gedeblokkeerd signaal of een SIGCHLD werd ontvangen; zie signal(7).

EINVAL
    Het opties argument was ongeldig.

ESRCH
    (voor wait() of waitpid()) pid is gelijk aan INT_MIN.

VERSIES

  C library/kernel verschillen
wait() is eigenlijk een bibliotheek functie die (in glibc) is geïmplementeerd als een aanroep naar wait4(2).

Op sommige architecturen, is er geen waitpid() systeem aanroep; in plaats daarvan, is dit interface geïmplementeerd door een C bibliotheek omwikkel functie die wait4(2) aanroept.

De ruwe waitid() systeem aanroep gebruikt het vijfde argument, van het type struct rusagefP. Als dit argument niet-NULL is, dan wordt het gebruikt om hulpbron informatie over het kind te retourneren, op dezelfde manier als wait4(2). Zie getrusage(2) voor details.

STANDAARDEN
POSIX.1-2024.

HISTORIE
SVr4, 4.3BSD, POSIX.1-2001.

OPMERKINGEN
Een kind dat stopt, maar waar niet op gewacht is wordt een "zombie". De kernel onderhoudt een minimale verzameling van informatie over het zombie proces (PID, beëindiging status, hulpbron gebruik informatie) om de ouder in staat te stellen om later te wachten om de informatie over het kind te verkrijgen. Zolang de zombie niet werd verwijderd door te wachten, zal het een item in de proces tabel van de kernel in beslag nemen, en als deze tabel vol is, is het niet meer mogelijk om meer processen te creëren. Als een ouder proces beëindigd, dan zullen zijn "zombie"kinderen (als die er zijn) worden geadopteerd door init(1), (of door het dichtstbijzijnde "maaimachine" proces zoals gedefinieerd door het gebruik van de prctl(2) PR_SET_CHILD_SUBREAPER operatie); init(1) voert automatisch een wacht uit om zombies te verwijderen.

POSIX.1-2001 specificeert dat als een dispositie van SIGCHLD is gezet op SIG_IGN of de SA_NOCLDWAIT vlag is gezet voor SIGCHLD (zie sigaction(2)), dan zullen kinderen die eindigen geen zombies worden en een aanroep van wait() of waitpid() zal blokkeren totdat alle kinderen beëindigd zijn, en vervolgens falen met errno gezet op ECHILD. (De originele POSIX standaard liet het gedrag van het zetten van SIGCHLD op SIG_IGN ongespecificeerd. Let op dat zelfs als de standaard dispositie van SIGCHLD "negeer" is, dan zal het expliciet zetten van de dispositie op SIG_IGN resulteren in een andere behandeling van zombie proces kinderen.)

Linux 2.6 voldoet aan de POSIX eisen. Hoewel Linux 2.4 (en eerder) dat niet deed: als een wait() of waitpid() aanroep wordt gedaan terwijl SIGCHLD wordt geïgnoreerd, dan gedraagt de aanroep zich alsof SIGCHLD niet geïgnoreerd werd, dat betekend, de aanroep blokkeert totdat het volgende kind stopt en vervolgens het proces ID en de status van dat kind teruggeeft.

  Linux notities
In de Linux kernel, een kernel-thread is niet anders van constructie dan een proces. In plaats daarvan, is een thread eenvoudig weg een proces dat werd aangemaakt door de Linux-unieke clone(2) systeem aanroep; andere routines zoals de overdraagbare pthread_create(3) aanroep zijn geïmplementeerd met clone(2). Voor Linux 2,4 was een thread slechts een speciaal geval van een proces, met als consequentie dat een thread niet kon wachten op kinderen of een andere thread, zelfs wanneer de laatste tot dezelfde thread groep behoorde. Echter, schrijft POSIX wel deze functionaliteit voor, en vanaf Linux 2.4 kan een thread, en doet dat ook standaard, wachten op kinderen of andere thread in dezelfde thread groep.

De volgende Linux-specifieke opties zijn alleen van toepassing op kinderen aangemaakt door clone(2); die kunnen ook gebruikt worden, sinds Linux 4.7, met waitid():

__WCLONE
    Wacht alleen op "kloon" kinderen. Als weggelaten, wacht dan alleen op "niet-kloon" kinderen. (Een "kloon"kind is er een dat geen signaal levert, of een signaal anders dan SIGCHLD aan zijn ouder bij beëindiging.) Deze optie wordt genegeerd als _WALL ook werd gespecificeerd.

__WALL (sinds Linux 2.4)
    Wacht op alle kinderen, van welk type ("kloon" of "niet-kloon") dan ook.

__WNOTHREAD (sinds Linux 2.4)
    Wacht niet op kinderen of andere threads in dezelfde thread groep. Dit was standaard voor Linux 2.4.

Vanaf Linux 4.7, is de __WALL vlag automatisch inbegrepen als het kind wordt ge-"ptraced".

BUGS
Volgens POSIX.1-2008 moet een applicatie die waitid() aanroept er voor zorgen dat infop wijst naar een siginfo_t structure (m.a.w. dat het een niet-null wijzer is). Op Linux, als infop gelijk is aan NULL, dan is waitid() succesvol en retourneert het proces ID van het kind waarop gewacht wordt. Applicaties moeten vermijden op dit inconsistent, niet-standaard en onnodige kenmerk te vertrouwen.

VOORBEELDEN
Het volgende programma demonstreert het gebruik van fork(2) en waitpid(). Het programma creëert een kind proces. Als geen commando regel argument mee gegeven werd naar het programma, dan schort het kind zijn uitvoer op door pause(2) te gebruiken, om zo toe te staan dat de gebruiker signalen naar het kind kan sturen. Anders, als wel een commando regel argument werd mee gegeven, dan stop het kind onmiddellijk, en gebruikt het gehele getal mee gegeven op de commando regel als de uitvoer status. Het ouder proces voert een lus uit die het kind door gebruik van waitpid() monitort, en gebruikt de W*() macros, zoals hierboven beschreven, om de wacht status waarde te analyseren.

De volgend shell sessie demonstreert het gebruik van het programma:

    $ ./a.out &
    Child PID is 32360
    [1] 32359
    $ kill -STOP 32360
    stopped by signal 19
    $ kill -CONT 32360
    continued
    $ kill -TERM 32360
    killed by signal 15
    [1]+  Done                    ./a.out
    $

  Programma bron
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>

    int
    main(int argc, char *argv[])
    {
        int    wstatus;
        pid_t  cpid, w;

        cpid = fork();
        if (cpid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        }

        if (cpid == 0) {            /* Code executed by child */
            printf("Child PID is %jd\n", (intmax_t) getpid());
            if (argc == 1)
                pause();                    /* Wait for signals */
            _exit(atoi(argv[1]));

        } else {                    /* Code executed by parent */
            do {
                w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);
                if (w == -1) {
                    perror("waitpid");
                    exit(EXIT_FAILURE);
                }

                if (WIFEXITED(wstatus)) {
                    printf("exited, status=%d\n", WEXITSTATUS(wstatus));
                } else if (WIFSIGNALED(wstatus)) {
                    printf("killed by signal %d\n", WTERMSIG(wstatus));
                } else if (WIFSTOPPED(wstatus)) {
                    printf("stopped by signal %d\n", WSTOPSIG(wstatus));
                } else if (WIFCONTINUED(wstatus)) {
                    printf("continued\n");
                }
            } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
            exit(EXIT_SUCCESS);
        }
    }

ZIE OOK
_exit(2), clone(2), fork(2), kill(2), ptrace(2), sigaction(2), signal(2), wait4(2), pthread_create(3), core(5), credentials(7), signal(7)

VERTALING
De Nederlandse vertaling van deze handleiding is geschreven door Jos Boersema <joshb@xs4all.nl>, Mario Blättermann <mario.blaettermann@gmail.com> en Luc Castermans <luc.castermans@gmail.com>

Deze vertaling is vrije documentatie; lees de GNU General Public License Version 3 (https://www.gnu.org/licenses/gpl-3.0.html) of later over de Copyright-voorwaarden. Er is geen AANSPRAKELIJKHEID.

Indien U fouten in de vertaling van deze handleiding zou vinden, stuur een e-mail naar debian-l10n-dutch@lists.debian.org.