2016-04-13 4 views
3

Wie kann der Masterprozess wissen, dass der untergeordnete Prozess die Datei nicht ausführen konnte (z. B. keine solche Datei oder kein solches Verzeichnis)? Im folgenden Code zum Beispiel können wir run() etwas anderes als 0 zurückgeben? Vielen Dank!execv und fork: Informieren Sie das übergeordnete Objekt, das die Datei nicht ausführen konnte

#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 = %d\n",pid); 

    if (pid == 0) 
    { 
     if (execv(proc,params)==-1) 
     { 
      error = immediateFailure; 
     } 
     printf("child: error = %d\n",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 = %d\n",error,waitError); 
    } 
    else 
    { 
     error = forkFailure; 
    } 

    return error; 
} 

int main(void) 
{ 
    printf("run() = %d\n",run()); 

    return 0; 
} 

Ausgang:

pid = 4286 
pid = 0 
child: error = 1 
run() = 1 
parent: error = 0, waitError = 0 
run() = 0 

Antwort

0

benötigen Sie den Fehlercode aus main oder exit() mit dem Wert zurückzukehren. Jetzt bist du in allen Fällen return in 0 von main, und das wird der Exit-Code des Kindes sein, das das Elternteil von waitpid erhält.

Die beste Lösung ist, exit(error) im Kind-Prozess hinzuzufügen:

printf("child: error = %d\n",error); 
exit(error); 

In jedem Fall Gebrauch ganzzahlige Konstanten anstelle von Zufall Enum Konstanten Enumeration. 1 und 2 sind häufige Rückgabewerte von vielen Unix-Befehlen, wobei 1 bedeutet, dass der Befehl nicht erfolgreich war (z. B. grep hat keine Übereinstimmungen gefunden), und 2+ bedeutet, dass der Befehl wirklich fehlgeschlagen ist (falsche Argumente o.ä.).

bash, zsh und andere Schalen verwenden 127 als Beendigungscode Befehl zu signalisieren, nicht gefunden/nicht runnable; so würde dies empfohlen:

#define COMMAND_NOT_RUNNABLE 127 

/* ... */ 

execv(proc, params); // exec never returns if successful. 
perror(proc); 
exit(COMMAND_NOT_RUNNABLE); 
0

Das Problem ist der Umgang mit dem Fehler nach dem execv ausfällt. Das Kind setzt error auf immediateFailure und gibt das an main zurück. Dann gibt main die Fehlernummer aus und gibt 0 zurück. Aber 0 bedeutet Erfolg, also denkt der Elternprozess, dass das Kind erfolgreich war.

Die Lösung besteht darin, die Fehlernummer von main zurückzugeben oder in dem Kindcode, z.

if (pid == 0) 
{ 
    execv(proc,params); 
    error = immediateFailure; 
    printf("child: error = %d\n",error); 
    exit(error); 
} 

Beachten Sie, dass Sie nicht brauchen, um den Rückgabewert von execv zu überprüfen, da execv nicht zurück, wenn es gelingt. Es wird nur zurückgegeben, wenn es fehlschlägt, und wird immer -1 zurückgeben.

0

Neben dem vorgeschlagenen exit(error); sollten Sie bestimmte Optionen für waitpid geben. Ihr Code hat nicht funktioniert, bis ich den Anruf zu waitpid(pid, &waitError, WUNTRACED | WCONTINUED);

geändert habe
Verwandte Themen