waitpid - WIFEXITED retourne 0 si la quitté normalement
J'ai écrit un programme qui génère un processus enfant, et les appels waitpid
attendre la terminaison du processus enfant. Le code est ci-dessous:
//fork & exec the child
pid_t pid = fork();
if (pid == -1)
//here is error handling code that is **not** triggered
if (!pid)
{
//binary_invocation is an array of the child process program and its arguments
execv(args.binary_invocation[0], (char * const*)args.binary_invocation);
//here is some error handling code that is **not** triggered
}
else
{
int status = 0;
pid_t res = waitpid(pid, &status, 0);
//here I see pid_t being a positive integer > 0
//and status being 11, which means WIFEXITED(status) is 0.
//this triggers a warning in my programs output.
}
La page de manuel de waitpid
unis pour WIFEXITED
:
WIFEXITED(status)
returns true if the child terminated normally, that is, by calling exit(3) or
_exit(2), or by returning from main().
Qui je intepret à dire qu'il doit retourner un entier != 0 en cas de succès, ce qui n'est pas le cas dans l'exécution de mon programme, depuis que j'ai observer WIFEXITED(status) == 0
Cependant, l'exécution du même programme à partir de la ligne de commande résultats dans $? == 0
, et à partir de gdb résultats dans:
[Inferior 1 (process 31934) exited normally]
Le programme se comporte normalement, à l'exception de l'déclenché l'alerte, qui me fait penser à quelque chose d'autre se passe ici, que je suis absent.
EDIT:
comme indiqué ci-dessous dans les commentaires, j'ai vérifié si l'enfant est résilié par erreur, et en effet, WIFSIGNALED(status)
retourne 1, et WTERMSIG(status)
renvoie 11, qui est SIGSEGV
.
Ce que je ne comprends pas bien, c'est pourquoi un appel à l'aide execv échoue avec une erreur de segmentation alors que le même appel à l'aide de gdb, ou un shell de réussir?
EDIT2:
Le comportement de mon application dépend fortement du comportement de l'enfant, en particulier sur un fichier de l'enfant, écrit dans une fonction déclarée __attribute__ ((destructor))
. Après la waitpid
retours d'appel, ce fichier existe et est correctement généré ce qui signifie que l'erreur de segmentation se produit quelque part dans un autre destructeur, ou quelque part en dehors de mon contrôle.
SIGSEGV
. Un non-signal de sortie est 256 fois plus élevé que les 8 bits de la valeur passée à _exit
ou exit
ou retourné par main
. Si vous êtes sur une plate-forme (comme Linux) qui a strace
, de l'utiliser (avec la -f
drapeau) pour voir si l'enfant reçoit le signal dû à une mauvaise appel à execv
, ou après le succès de l'exec.vous avez raison! Je n'étais pas conscient du fait que l'octet de poids faible de la variable d'état est titulaire d'état de sortie du processus générés dynamiquement, ainsi que le signal id. merci pour cette remarque!
"Ce que je ne comprends pas bien, c'est pourquoi un appel à l'aide execv échoue avec une erreur de segmentation" ... comment ne
args.binary_invocation
ressembler ? D'où il vient, vous le créer ?oui, args.binary_invocation est une valeur NULL tableau de pointeurs de char qui sont le nom de l'enfant, de l'application et de ses arguments. J'ai vérifié que le tableau est correct.
J'ai trouvé la raison de l'erreur de segmentation merci pour votre commentaire, le problème était que mon application ont modifié l'environnement pour le processus de l'enfant, que je n'ai pas reproduire dans mes tests indépendants, c'est pourquoi l'erreur de segmentation a été caché à l'extérieur de l'exec de l'environnement. Je voudrais vous donner crédit pour cela, parce que vous m'avez envoyé dans la bonne direction. Donc, si vous souhaitez faire vos commentaires en réponse à une question, je serais heureux de les recevoir 🙂
OriginalL'auteur Andreas Grapentin | 2014-04-24
Vous devez vous connecter pour publier un commentaire.
Sur les systèmes Unix et Linux, l'état renvoyé de
wait
ouwaitpid
(ou l'une de l'autrewait
variantes) a cette structure:(Notez que Posix ne pas définir les choses, les macros, mais ce sont les bits les définitions utilisées par au moins Linux, Mac OS X/iOS, et Solaris. Notez également que
waitpid
renvoie uniquement pour stopper les événements si vous passer leWUNTRACED
drapeau et la suite des événements si vous passer leWCONTINUED
drapeau.)Donc un état de 11 signifie que l'enfant a quitté en raison de signal 11, qui est
SIGSEGV
(encore une fois, pas Posix, mais conventionnelle).Soit votre programme est le passage d'arguments non valides pour
execv
(qui est une bibliothèque C wrapper autour deexecve
ou une autre noyau d'appel), ou de l'enfant est différent lorsque vousexecv
et quand vous l'exécutez à partir de la coque ou de gdb.Si vous êtes sur un système qui prend en charge
strace
, l'exécution de votre (parent) programme sousstrace -f
pour voir siexecv
est à l'origine du signal.Merci. J'ai corrigé la réponse.
OriginalL'auteur rob mayoff