execv kehrt nicht zurück



  • System: Linux
    Sprache: C++

    Hi,

    ich habe ein Problem bei meinem Projekt: Es soll ein anderes Programm mit Parametern aufrufen und dann Informationen ausgeben.
    Das Problem dabei ist, dass execv ja nur (afaik) zurückkehrt, wenn ein Fehler vorliegt. Es soll aber auch zurückkehren, wenn 0 (also kein Fehler) zurückgegeben wird.

    Ist das mit execv möglich oder brauche ich einen anderen Befehl?
    Mein Programm hört nämlich nach dem execv einfach auf.

    mfg



  • Die exec funktionen werden bei Erfolg nie zurückkehren. Wenn man einen Unterprozess starten will, benutzt man fork und exec.



  • Hi Ponto,

    vielen Dank für deine Hilfe, mein Programm läuft schonmal weiter.
    Jetzt hätte ich noch ein Problem: Irgendwie will die fork&exec Funktion den return Wert des anderen Programms nicht abfangen. Hast du ein Beispiel-Programm/Link?

    int b = exec(..); klappt nämlich irgendwie nicht.

    mfg



  • debp schrieb:

    Hi Ponto,

    vielen Dank für deine Hilfe, mein Programm läuft schonmal weiter.
    Jetzt hätte ich noch ein Problem: Irgendwie will die fork&exec Funktion den return Wert des anderen Programms nicht abfangen. Hast du ein Beispiel-Programm/Link?

    int b = exec(..); klappt nämlich irgendwie nicht.

    mfg

    Wenn sich der Kindprozess beendet, wird das Signal SIGCHLD an den Parent gesendet. Dieser kann dann mittels waitpid auf das Kind warten und auch den Return Wert auswerten:

    man waitpid



  • Vielen Dank.

    PS: Für alle, die das Problem auch haben: Erklärung|Beispielprogramme

    mfg



  • Habe mich wohl zu früh gefreut 🙂

    #include <sys/wait.h>
    #include <iostream>
    
    int main()
    {
    	int status;
    
    	switch(fork())
    	{
    		case 0: exit(execv(...));
    			break;
    
    		default: wait(&status);
    
    			 if(WIFEXITED(status))
    			 {
    			 	std::cout<<WEXITSTATUS(status)<<std::endl;
    			 }
    	}
    
    	return 0;
    }
    

    Das Problem ist wieder mal der return-Wert: Das Programm kehrt ja nicht zum exit() zurück. Wie mach ich das jetzt?

    mfg



  • Das exit() wird aufgerufen, wenn das exec nicht klappt. Das ist dazu da, dass nicht irgendwas ungewolltes ausgeführt wird.

    Ich glaube du hast exec() noch nicht ganz verstanden. Diese Funktion sorgt, dafür, dass das aktuelle Programm vollständig durch ein anderes ersetzt wird. Das geschieht im selben Prozess. Es wird kein neuer Prozess gestartet. Das alte Programm hört komplett auf zu existieren und das neue beginnt. Ein nicht existierendes Programm kann aber keinen return Wert auslesen.



  • Wie lese ich denn nun den return-Wert eines Programmes ein?

    mfg



  • debp schrieb:

    Wie lese ich denn nun den return-Wert eines Programmes ein?

    mfg

    So wie du es im Code gemacht hast. Nur der Parent darf das und der kann es mit
    WEXITSTATUS(status) machen.



  • Ja, aber das funktioniert ja nicht, da alle exec Varianten nicht zurückkehren.

    Zur Erklärung: Ich habe viele Programme, die lokal miteinander kommunizieren sollen. Daher brauche ich den return Wert (nicht einer Funktion, sondern eines _Programms_).

    mfg



  • debp schrieb:

    Ja, aber das funktioniert ja nicht, da alle exec Varianten nicht zurückkehren.

    Zur Erklärung: Ich habe viele Programme, die lokal miteinander kommunizieren sollen. Daher brauche ich den return Wert (nicht einer Funktion, sondern eines _Programms_).

    mfg

    Das wait wartet darauf, dass das Kind fertig ist. Und das wait speichert den Rückgabewert in status. Und das wird dann ausgewertet.



  • Mh.. ich wüsste nicht, wie mir das jetzt helfen sollte.

    Hast du einen Codeschnipsel oder sowas in der Richtung?

    Das wait speichert ja nicht den return Wert des _Programms_.

    mfg



  • Hier mal ein Programm, dass einen neuen Prozess startet, der direkt mit 42 terminiert.

    extern  "C" {
    #include <unistd.h>
    #include <sys/types.h> 
    #include <sys/wait.h>
    }
    
    #include <iostream>
    
    int main()
    {
    
       switch (fork()) {
    
          case -1:
             std::cerr << "Creation of new process failed\n";
             exit(-1);
          case  0:         //Childprocesss
             std::cout << "Childprocess started returning 42\n";
             return 42;
          default:
             int status;
             if (wait(&status) < 0) {
                std::cerr << "Error waiting for child process\n";
             }
             std::cout << "Child terminated with return code: " << WEXITSTATUS(status) << "\n";
       }
       return 0;
    }
    


  • *waahh*

    Ich red gegen 'ne Wand 😉

    Beispiel:

    // programm1
    int main(int argc, char** argv)
    {
        if(atoi(argv[1]) == 1)
            return 0;
    
        return 1;
    }
    
    // programm2, welches programm1 aufrufen und return wert abfangen soll
    int main()
    {
        execl("./programm1", "./programm1", "arg", "arg".., 0);
    
    // dann brauch ich den return wert des programms 1
        if(/*return-wert des programms*/)
        { ..... }
    
        return 0;
    }
    

    Verstehst du jetzt was ich meine?

    PS: Ich weiß, dass execl nicht mehr zurückkehrt, aber das habe ich ja sogar im ersten Posting gesagt.

    mfg



  • Mein Beispiel hatte schon alles:

    extern  "C" {
    #include <unistd.h>
    #include <sys/types.h> 
    #include <sys/wait.h>
    }
    
    #include <iostream>
    
    int main()
    {
    
       switch (fork()) {
    
          case -1:
             std::cerr << "Creation of new process failed\n";
             exit(-1);
          case  0:         //Childprocesss
             execl("./programm1", "./programm1", "arg", "arg", 0);
             exit(-1);
          default:
             int status;
             if (wait(&status) < 0) {
                std::cerr << "Error waiting for child process\n";
             }
             std::cout << "Der Rückgabewert von programm1 ist: " << WEXITSTATUS(status) << "\n";
       }
       return 0;
    }
    


  • case  0:         //Childprocesss
             execl("./programm1", "./programm1", "arg", "arg", 0);
             exit(-1);
    

    Nach der execl-Zeile stoppt das Programm (bzw. child-Prozess). exit(-1) wird nicht aufgerufen.

    mfg



  • debp schrieb:

    case  0:         //Childprocesss
             execl("./programm1", "./programm1", "arg", "arg", 0);
             exit(-1);
    

    Nach der execl-Zeile stoppt das Programm (bzw. child-Prozess). exit(-1) wird nicht aufgerufen.

    mfg

    Und wo ist das Problem? Hast du den Code mal ausgeführt? was ist passiert?



  • *confused*

    Nanu, jetzt klappt es... ;).

    Ich war mir 99% sicher, dass ich das vorher schon so hatte.

    Vielen Dank :).

    Mit freundlichen Grüßen
    debp


Anmelden zum Antworten