/ / execv et fork: informer le parent que l'enfant n'a pas pu exécuter le fichier - c, fork, waitpid, execv

execv et fork: informer le parent que l'enfant n'a pas pu exécuter le fichier - c, fork, waitpid, execv

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 № 1

Vous devez renvoyer le code d'erreur de main, ou exit() avec la valeur. Maintenant vous êtes returning 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);