wait(2) System Calls Manual wait(2) NOM wait, waitpid, waitid - Attendre la fin d'un processus BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS #include pid_t wait(int *_Nullable wstatus); pid_t waitpid(pid_t pid, int *_Nullable wstatus, int options); int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); /* Il s'agit de l'interface de glibc et POSIX ; consultez les NOTES pour des informations sur les appels systeme bruts. */ Exigences de macros de test de fonctionnalites pour la glibc (consulter feature_test_macros(7)) : waitid() : Depuis la glibc 2.26 : _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L Pour la glibc anterieure et egale a 2.25 : _XOPEN_SOURCE || /* Depuis la glibc 2.12: */ _POSIX_C_SOURCE >= 200809L || /* glibc <= 2.19: */ _BSD_SOURCE DESCRIPTION Tous ces appels systeme attendent qu'un des enfants du processus appelant change d'etat et permettent d'obtenir des informations sur l'enfant en question. Un processus est considere comme changeant d'etat s'il termine, s'il est stoppe par un signal ou s'il est relance par un signal. Dans le cas d'un enfant qui se termine, l'attendre permet au systeme de liberer les ressources qui lui etaient allouees ; si le processus n'est pas attendu, il reste en etat de << zombie >> (voir les NOTES plus bas). Si un enfant a deja change d'etat, ces appels systeme retournent immediatement. Sinon, ils bloquent jusqu'a ce qu'un enfant change d'etat ou qu'un gestionnaire de signal interrompe l'appel (sauf si les appels systeme sont relances automatiquement par l'option SA_RESTART de sigaction(2)). Dans la suite de cette page, un enfant qui a change d'etat et qui n'a pas ete attendu est appele pret (waitable). wait() et waitpid() L'appel systeme wait() suspend l'execution du processus appelant jusqu'a ce que l'un de ses enfants se termine. L'appel wait(&status) est equivalent a : waitpid(-1, &wstatus, 0); L'appel systeme waitpid() suspend l'execution du processus appelant jusqu'a ce qu'un enfant specifie par l'argument pid change d'etat. Par defaut, waitpid() n'attend que les enfants termines, mais ce comportement peut etre modifie par l'argument options, de la facon decrite ci-dessous. La valeur de pid peut etre l'une des suivantes : < -1 Attendre la fin de n'importe quel processus enfant appartenant au groupe de processus d'ID -pid. -1 Attendre n'importe lequel des processus enfant. 0 Attendre la fin de n'importe quel processus enfant dont l'identifiant de groupe du processus est egal a celui du processus appelant au moment de l'appel a waitpid(). > 0 Attendre la fin d'un enfant dont l'identifiant du processus est egal a la valeur du processus numero pid. La valeur de l'argument option options est un OU binaire entre zero ou plus des constantes suivantes : WNOHANG Ne pas bloquer si aucun enfant ne s'est termine. WUNTRACED Recevoir l'information concernant egalement les enfants bloques (mais non suivis par ptrace(2)). L'etat des enfants suivis qui se sont termines est fourni meme sans cette option. WCONTINUED (Depuis Linux 2.6.10) Renvoyer egalement si un processus enfant stoppe a ete relance par le signal SIGCONT. (Pour les options specifiques a Linux, voir plus bas.) Si wstatus n'est pas NULL, wait() et waitpid() stockent l'etat de l'enfant dans la variable de type int pointee. Cet entier peut etre evalue avec les macros suivantes (qui prennent l'entier lui-meme comme argument, et pas un pointeur vers celui-ci, comme le font wait() et waitpid() !) : WIFEXITED(wstatus) Vrai si l'enfant s'est termine normalement, c'est-a-dire par un appel a exit(3) ou _exit(2) ou par un return depuis main(). WEXITSTATUS(wstatus) Donne le code de retour, consistant en les 8 bits de poids faible du parametre status fourni a exit(3) ou _exit(2) ou dans le return de la routine main(). Cette macro ne peut etre evaluee que si WIFEXITED a renvoye vrai. WIFSIGNALED(wstatus) Vrai si l'enfant s'est termine a cause d'un signal. WTERMSIG(wstatus) Donne le numero du signal qui a cause la fin de l'enfant. Cette macro ne peut etre evaluee que si WIFSIGNALED a renvoye vrai. WCOREDUMP(wstatus) Vrai si le processus enfant a produit une image memoire (<< core dump >>) (voir core(5)). Cette macro ne doit etre evaluee que si WIFSIGNALED a renvoye vrai. Cette macro n'est pas decrite par POSIX.1-2001 et n'est pas disponible sur certaines implementations d'UNIX (par exemple AIX ou SunOS). N'utilisez cette macro qu'entouree de #ifdef WCOREDUMP ... #endif. WIFSTOPPED(wstatus) Vrai si le processus enfant a ete arrete par l'envoi d'un signal. Cela n'est possible que si l'on a effectue l'appel avec l'option WUNTRACED ou si l'enfant est suivi (voir ptrace(2)). WSTOPSIG(wstatus) Donne le numero du signal qui a cause l'arret de l'enfant. Cette macro ne peut etre evaluee que si WIFSTOPPED renvoie vrai. WIFCONTINUED(wstatus) (Depuis Linux 2.6.10) Vrai si le processus enfant a ete relance par SIGCONT. waitid() L'appel systeme waitid(), disponible depuis Linux 2.6.9, fournit des moyens plus fins de controler quels changements d'etats attendre. Les arguments idtype et id selectionnent le(s) enfant(s) a attendre, comme suit : idtype == P_PID Attendre la fin de l'enfant dont l'identifiant du processus correspond a id. idtype == P_PIDFD (depuis Linux 5.4) Attendre la fin de l'enfant auquel fait reference le descripteur de fichier PID specifie dans id (voir pidfd_open(2) pour plus d'informations a propos des descripteurs de fichier PID). idtype == P_PGID Attendre la fin de l'enfant dont l'identifiant de groupe du processus correspond a id. depuis Linux 5.4, si id vaut zero, attendre pour n'importe quel enfant qui est dans le meme groupe de processus que le groupe de processus de l'appelant au moment de l'appel. idtype == P_ALL Attendre n'importe quel enfant ; l'argument id est ignore. Les changements d'etat a attendre sont indiques par un OU binaire des attributs suivants dans le parametre options : WEXITED Attendre les enfants qui se sont termines. WSTOPPED Attendre les enfants qui ont ete arretes par un signal. WCONTINUED Attendre les enfants precedemment arretes qui ont ete relances par le signal SIGCONT. Les attributs suivants peuvent egalement etre utilises dans options : WNOHANG Comme pour waitpid(). WNOWAIT Laisser l'enfant dans un etat pret ; un appel ulterieur a wait() pourra de nouveau fournir des informations sur l'etat de l'enfant. Si l'appel reussit, waitid() remplit les champs suivants de la structure siginfo_t pointee par infop : si_pid L'identifiant de processus de l'enfant. si_uid L'UID reel de l'enfant. Ce champ n'est pas rempli par la plupart des autres implementations. si_signo Toujours SIGCHLD. si_status Soit le code de retour de l'enfant donne a _exit(2) ou exit(3), soit le signal ayant provoque la terminaison, l'arret ou la relance de l'enfant. Le champ si_code permet de savoir comment interpreter ce champ. si_code L'un de CLD_EXITED (l'enfant a appele _exit(2)), CLD_KILLED (l'enfant a ete tue par un signal), CLD_DUMPED (l'enfant a ete tue par un signal et a produit une image memoire (core dump)), CLD_STOPPED (l'enfant a ete arrete par un signal), CLD_TRAPPED (l'enfant suivi a ete capture) ou CLD_CONTINUED (l'enfant a ete relance par SIGCONT). Si WNOHANG est utilise dans options et si aucun enfant n'est pret, waitid() renvoie 0 immediatement et l'etat de la structure siginfo_t pointee par infop depend de l'implementation. Pour differencier (de facon portable) ce cas de celui ou un des enfants etait pret, definissez a zero le champ si_pid avant l'appel, et verifiez que sa valeur est differente de zero apres le renvoi de l'appel. Le premier rectificatif technique POSIX.1-2008 (2013) ajoute l'exigence que quand WNOHANG est specifie dans options et si aucun enfant n'est pret, waitid() doit definir a zero les champs si_pid et si_signo de la structure. Dans Linux et d'autres implementations qui respectent cette exigence, il n'est pas necessaire de definir a zero le champ si_pid avant l'appel a waitid(). Neanmoins, toutes les implementations ne suivent pas la specification de POSIX.1 sur ce point. VALEUR RENVOYEE wait() : en cas de reussite, l'identifiant du processus enfant termine est renvoye ; en cas d'echec, la valeur de retour est -1. waitpid() : s'il reussit, l'appel renvoie l'identifiant du processus enfant dont l'etat a change ; si WNOHANG est utilise et si un enfant (ou plus) specifie par pid existe, mais n'a pas encore change d'etat, la valeur renvoyee est 0. En cas d'echec, -1 est renvoye. waitid() : renvoie 0 s'il reussit ou si WNOHANG est utilise et siaucun enfant specifie dans id n'a encore change d'etat. En cas d'echec, renvoie -1. En cas d'echec, chacun de ces appels definit errno pour preciser l'erreur. ERREURS EAGAIN Le descripteur de fichier PID specifie dans id n'est pas bloquant et le processus auquel il fait reference ne s'est pas termine. ECHILD (pour wait()) Le processus appelant n'a pas d'enfants qui n'ont pas ete attendus. ECHILD (pour waitpid() ou waitid()) Le processus indique par pid (waitpid()) ou idtype et id (waitid()) n'existe pas ou n'est pas un enfant du processus appelant. (Cela peut arriver pour son propre enfant si l'action de SIGCHLD est definie a SIG_IGN ; voir egalement le passage de la section Notes sur Linux concernant les threads.) EINTR WNOHANG n'est pas indique et un signal a intercepter ou SIGCHLD a ete recu ; consultez signal(7). EINVAL L'argument options n'est pas valable. ESRCH (pour wait() ou waitpid()) pid est equivalent a INT_MIN. VERSIONS Differences entre bibliotheque C et noyau wait() est en fait une fonction de bibliotheque implementee (dans glibc) en tant qu'appel systeme a wait4(). sur certaines architectures, il n'y a pas d'appel systeme waitpid() ; a la place, cette interface est implementee au moyen d'une fonction d'enveloppe de la bibliotheque C qui appelle wait4(2). L'appel systeme brut waitid() prend un cinquieme parametre, de type struct rusage *. Si ce parametre n'est pas NULL, il est utilise pour renvoyer les informations d'utilisation des ressources au sujet du thread enfant, de la meme facon que wait4(2). Consultez getrusage(2) pour plus de details. STANDARDS POSIX.1-2008. HISTORIQUE SVr4, 4.3BSD, POSIX.1-2001. NOTES Un enfant qui se termine mais n'a pas ete attendu devient un << zombie >>. Le noyau conserve des informations minimales sur le processus zombie (identifiant, code de retour, informations d'utilisation des ressources) pour permettre au parent de l'attendre plus tard et d'obtenir des informations sur l'enfant. Tant que le zombie n'est pas efface du systeme par une attente, il prendra un emplacement dans la table des processus du noyau, et si cette table est remplie, il sera impossible de creer de nouveaux processus. Si un processus parent se termine, ses enfants zombies (s'il y en a) sont adoptes par init(1) (ou par le processus suppresseur (subreaper) le plus proche tel que defini par l'utilisation de l'operation PR_SET_CHILD_SUBREAPER de prctl(2)) ; init(1) les attend automatiquement pour supprimer les zombies. POSIX.1-2001 indique que si l'action pour SIGCHLD est definie a SIG_IGN ou si l'attribut SA_NOCLDWAIT est indique pour SIGCHLD (voir sigaction(2)), les enfants qui se terminent ne deviennent pas des zombies et un appel a wait() ou waitpid() sera bloquant jusqu'a ce que tous les enfants soient termines, et echouera ensuite en positionnant errno a ECHILD. (La norme POSIX originale ne decrivait pas le comportement si l'action pour SIGCHLD etait SIG_IGN. Veuillez noter que meme si la disposition par defaut de SIGCHLD est << ignore >>, la configuration explicite de la disposition de SIG_IGN entraine un traitement different des processus enfants zombies.) Linux 2.6 est conforme aux preconisations de POSIX. Cependant, Linux 2.4 et les versions anterieures ne l'etaient pas. Lorsqu'un appel wait() ou waitpid() etait execute en ignorant SIGCHLD, les appels se comportaient comme si SIGCHLD etait pris en compte, c'est a dire que l'appel restait bloque en attendant que l'enfant suivant se termine, puis renvoyait l'identifiant de processus et l'etat de cet enfant. Notes pour Linux Dans le noyau Linux, un thread ordonnance par le noyau n'est pas different d'un simple processus. En fait, un thread est juste un processus qui est cree a l'aide de la routine -- specifique a Linux -- clone(2). Les routines portables, comme pthread_create(3), sont implementees en appelant clone(2). Avant Linux 2.4, un thread etait simplement un cas particulier de processus, et en consequence un thread ne pouvait pas attendre les enfants d'un autre thread, meme si ce dernier appartenait au meme groupe de threads. Toutefois, POSIX reclame une telle fonctionnalite, et depuis Linux 2.4 un thread peut, par defaut, attendre les enfants des autres threads du meme groupe. Les options suivantes sont specifiques a Linux et servent pour les enfants crees avec clone(2) ; elles peuvent aussi, depuis Linux 4.7, etre utilisees avec waitid() : __WCLONE Attendre uniquement des enfants clones. Sinon, attendre uniquement les enfants non-clones (un enfant << clone >> est un enfant qui n'envoie pas de signal ou un autre signal que SIGCHLD a son pere a sa terminaison). Cette option est ignoree si __WALL est aussi indique. __WALL (depuis Linux 2.4) Attendre tous les enfants, quel que soit leur type (clone ou non-clone). __WNOTHREAD (Depuis Linux 2.4) Ne pas attendre les enfants des autres threads du meme groupe de threads. Cela etait le cas par defaut avant Linux 2.4. Depuis Linux 4.7, l'attribut __WALL est automatiquement implique si l'enfant est suivi. BOGUES Selon la norme POSIX.1-2008, une application appelant waitid() doit garantir que infop pointe sur une structure siginfo_t (c'est-a-dire qu'elle ne pointe pas sur NULL). Sur Linux, si infop est NULL, waitid() reussit, et renvoie l'identificateur du processus enfant attendu. Dans la mesure du possible, les applications doivent eviter d'avoir recours a cette fonctionnalite incoherente, non standard et superflue. EXEMPLES Le programme suivant montre l'utilisation de fork(2) et de waitpid(). Le programme cree un processus enfant. Si aucun argument n'est fourni dans la ligne de commande du programme, l'enfant suspend son execution avec pause(2), pour que l'utilisateur puisse lui envoyer des signaux. Sinon, l'enfant se termine immediatement en utilisant l'entier fourni sur la ligne de commande comme code de retour. Le processus pere boucle en surveillant l'etat de l'enfant avec waitpid() et utilise les macros W*() decrites ci-dessus pour analyser le code d'etat de l'enfant. La session interactive suivante montre l'utilisation de ce programme : $ ./a.out & Le PID de l'enfant est 32360 [1] 32359 $ kill -STOP 32360 arrete par le signal 19 $ kill -CONT 32360 relance $ kill -TERM 32360 tue par le signal 15 [1]+ Done ./a.out $ Source du programme #include #include #include #include #include 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 execute par l'enfant */ printf("Child PID is %jd\n", (intmax_t) getpid()); if (argc == 1) pause(); /* Attendre un signal */ _exit(atoi(argv[1])); } else { /* Code execute par le parent */ do { w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(wstatus)) { printf("termine, code=%d\n", WEXITSTATUS(wstatus)); } else if (WIFSIGNALED(wstatus)) { printf("tue par le signal %d\n", WTERMSIG(wstatus)); } else if (WIFSTOPPED(wstatus)) { printf("arrete par le signal %d\n", WSTOPSIG(wstatus)); } else if (WIFCONTINUED(wstatus)) { printf("relance\n"); } } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus)); exit(EXIT_SUCCESS); } } VOIR AUSSI _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) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot , Cedric Boutillier , Frederic Hantrais et Jean-Pierre Giraud Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 31 octobre 2023 wait(2)