Comment le processus maître peut-il savoir que l'enfantprocessus n’a pas pu exécuter le fichier (par exemple, aucun fichier ou répertoire de ce type)? Par exemple, dans le code suivant, comment pouvons-nous exécuter run () pour retourner autre chose que 0? Merci!
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
enum ErrorType { noError, immediateFailure, returnFailure, forkFailure };
using namespace std;
int run(void)
{
int error = noError;
//char proc[] = "/bin/uname";
char proc[] = "/usr/bin/Idontexist";
char *const params[] = {proc, NULL};
pid_t pid = fork();
printf("pid = %dn",pid);
if (pid == 0)
{
if ( execv(proc,params)==-1 )
{
error = immediateFailure;
}
printf("child: error = %dn",error);
}
else if (pid > 0)
{
/* This is the parent process
* incase you want to do something
* like wait for the child process to finish
*/
int waitError;
waitpid(pid, &waitError, 0);
if ( waitError )
error = returnFailure;
printf("parent: error = %d, waitError = %dn",error,waitError);
}
else
{
error = forkFailure;
}
return error;
}
int main(void)
{
printf("run() = %dn",run());
return 0;
}
sortie:
pid = 4286
pid = 0
child: error = 1
run() = 1
parent: error = 0, waitError = 0
run() = 0
Réponses:
0 pour la réponse № 1Vous devez renvoyer le code d'erreur de main
, ou exit()
avec la valeur. Maintenant vous êtes return
ing 0
de main
dans tous les cas, et ce sera le code de sortie de l'enfant que le parent reçoit de waitpid
.
La meilleure solution consiste à ajouter exit(error)
dans le processus fils:
printf("child: error = %dn",error);
exit(error);
Dans tous les cas, utilisez des constantes entières au lieu des constantes enum aléatoires enum. 1 et 2 sont des valeurs de retour communes à de nombreuses commandes unix, avec 1 signifiant que la commande a échoué (par exemple grep
n’a trouvé aucune correspondance) et 2+ signifiant que la commande a vraiment échoué (arguments incorrects ou autres)
bash
, zsh
et d'autres coquilles utilisent 127
comme code de sortie pour signaler commande non trouvée / non exécutable; donc ceci serait recommandé:
#define COMMAND_NOT_RUNNABLE 127
/* ... */
execv(proc, params); // exec never returns if successful.
perror(proc);
exit(COMMAND_NOT_RUNNABLE);
0 pour la réponse № 2
Le problème est la gestion de l'erreur après la execv
échoue. L'enfant met error
à immediateFailure
et retourne à main
. alors main
affiche le numéro d'erreur et retourne 0
. Mais 0
signifie succès, donc le processus parent pense que l'enfant a réussi.
La solution consiste à renvoyer le numéro d'erreur de main
, ou appeler exit
dans le code enfant, par exemple
if (pid == 0)
{
execv(proc,params);
error = immediateFailure;
printf("child: error = %dn",error);
exit( error );
}
Notez que vous n’avez pas besoin de vérifier la valeur de retour de execv
, depuis execv
ne reviendra pas s'il réussit. Il ne reviendra que s'il échoue et retournera toujours -1.
0 pour la réponse № 3
En plus de la proposition exit(error);
vous devriez donner des options spécifiques pour waitpid
. Votre code n'a pas fonctionné pour moi jusqu'à ce que j'ai changé l'appel à waitpid(pid, &waitError, WUNTRACED | WCONTINUED);