HOWTO · C
Utilisez la fonction waitpid en C
Cet article explique comment utiliser la fonction waitpid en C
Sur cette page
Utilisez waitpid lorsqu’un processus parent doit récupérer le statut d’un processus enfant, qu’il s’agisse d’un enfant précis ou de n’importe quel enfant admissible. Les arguments permettent de choisir l’enfant et les changements d’état à signaler. Le statut renvoyé doit être décodé à l’aide des macros de <sys/wait.h> et ne doit pas être traité directement comme un code de sortie.
Utiliser waitpid pour attendre un enfant précis
Un processus peut créer un enfant avec fork. L’enfant poursuit son exécution à partir du point d’appel, tandis que le parent reçoit l’identifiant de processus de l’enfant. Le parent doit récupérer le statut d’un enfant terminé au moyen d’un appel de la famille des fonctions d’attente afin de pouvoir consulter son statut de terminaison et le récolter.
L’appel a la forme waitpid(pid, &status, options). Un pid positif sélectionne ce processus enfant. La valeur -1 sélectionne n’importe quel enfant dont l’état correspond aux options ; c’est la sélection utilisée par wait. La valeur 0 sélectionne les enfants appartenant au groupe de processus de l’appelant. Une valeur inférieure à -1 sélectionne les enfants du groupe de processus dont l’identifiant est la valeur absolue de pid. waitpid permet donc de cibler un enfant, mais ce n’est pas la seule interface de la famille des fonctions d’attente pour attendre des enfants.
Le deuxième argument pointe vers un entier dans lequel le noyau stocke un statut encodé lorsqu’un changement d’état de l’enfant est signalé. Transmettez un pointeur valide si vous avez besoin de ce statut. Le troisième argument est un masque de bits d’options. Lorsque les options valent 0, l’appel attend la terminaison de l’enfant sélectionné. Il bloque si aucun changement d’état correspondant n’est prêt.
Choisir les événements des enfants à signaler
WNOHANG rend l’appel non bloquant : si aucun enfant sélectionné n’a de changement d’état à signaler, waitpid renvoie immédiatement 0. Le parent peut ainsi effectuer d’autres tâches et vérifier à nouveau plus tard. Une valeur de retour positive est l’identifiant du processus enfant dont le statut a été écrit. WUNTRACED signale aussi un enfant arrêté qui ne l’a pas encore été, et WCONTINUED signale un enfant qui a repris son exécution après un arrêt. Ces options définissent les changements d’état qui peuvent satisfaire un appel ; un seul appel ne surveille pas toutes les transitions à venir. Combinez les indicateurs avec l’opérateur OU bit à bit, par exemple WUNTRACED | WCONTINUED.
Décoder le statut renvoyé par waitpid
L’entier de statut est encodé et doit être examiné à l’aide des macros correspondantes. WIFEXITED(status) indique une terminaison normale ; WEXITSTATUS(status) extrait alors le code de sortie. WIFSIGNALED(status) indique une terminaison causée par un signal, et WTERMSIG(status) donne ce signal. Si les enfants arrêtés sont demandés, WIFSTOPPED(status) et WSTOPSIG(status) permettent d’identifier l’arrêt. Si elle est prise en charge et demandée, WIFCONTINUED(status) indique qu’un enfant a repris son exécution. WCOREDUMP n’est disponible que sur certains systèmes ; le code qui l’utilise doit donc vérifier sa disponibilité avec une condition du préprocesseur. Ces macros sont déclarées dans <sys/wait.h>.
N’appelez WEXITSTATUS que si WIFEXITED est vrai, et WTERMSIG que si WIFSIGNALED est vrai. L’entier n’est pas lui-même le code de sortie de l’enfant ; les macros évitent de dépendre de la disposition de bits propre à l’implémentation.
Gérer les valeurs de retour et les erreurs
Un résultat de waitpid supérieur à zéro identifie l’enfant dont le statut a été récupéré. Le résultat 0 signifie qu’aucun statut correspondant n’est prêt ; il apparaît avec WNOHANG. Le résultat -1 signale une erreur : examinez errno pour en déterminer la cause. Par exemple, ECHILD signifie qu’aucun enfant ne correspond à la sélection, tandis que EINTR signifie qu’un signal intercepté a interrompu l’attente. Si le programme doit continuer à attendre après EINTR, relancez l’appel ; sinon, gérez l’interruption conformément à la politique de signaux de l’application. Sans WNOHANG, l’appel peut aussi bloquer indéfiniment si l’enfant sélectionné continue de s’exécuter et qu’aucun changement d’état demandé ne se produit.
Exécuter un exemple complet avec un processus enfant
Cet exemple POSIX crée un enfant, attend précisément sa terminaison, réessaie si un signal interrompt l’attente et affiche le code de sortie décodé. Il utilise fork et waitpid et ne dépend ni d’un programme séparé ni d’une saisie interactive. Le code est destiné à un environnement POSIX doté d’un compilateur C ; il n’est pas présenté comme portable en C ISO. Les éléments d’exécution fournis indiquent une exécution réussie, avec un code de sortie égal à 0 et la sortie affichée ci-dessous.
Exécutez cet exemple :
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void) {
pid_t child = fork();
if (child == -1) {
perror("fork");
return EXIT_FAILURE;
}
if (child == 0) {
_exit(7);
}
int status;
pid_t result;
do {
result = waitpid(child, &status, 0);
} while (result == -1 && errno == EINTR);
if (result == -1) {
perror("waitpid");
return EXIT_FAILURE;
}
if (WIFEXITED(status)) {
printf("child exit status: %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("child terminated by signal: %d\n", WTERMSIG(status));
}
return EXIT_SUCCESS;
}
child exit status: 7