tags:

views:

1521

answers:

3

In my simple custom shell I'm reading commands from the standard input and execute them with execvp(). Before this, I create a fork of the current process and I call the execvp() in that child process, right after that, I call exit(0).

Something like this:

pid = fork();

if(pid == -1) {
    perror("fork");
    exit(1);
}

if(pid == 0) {
    // CHILD PROCESS CODE GOES HERE...
    execvp(pArgs[0], pArgs);
    exit(0);
} else {
    // PARENT PROCESS CODE GOES HERE...
}

Now, the commands run with execvp() can return errors right? I want to handle that properly and right now, I'm always calling exit(0), which will mean the child process will always have an "OK" state.

How can I return the proper status from the execvp() call and put it in the exit() call? Should I just get the int value that execvp() returns and pass it as an exit() argument instead of 0. Is that enough and correct?

+4  A: 

You need to use waitpid(pid) in the parent code to wait for the child to exit and get the error message.

The syntax is:

pid_t waitpid(pid_t pid, int *status, int options);

status contains the exit status. Look at man waitpid to see you how to parse it.


Note that you can't do this from the child process. Once you call execvp the child process dies (for all practical purposes) and is replaced by the exec'd process. The only way you can reach exit(0) there is if execvp itself fails, but then the failure isn't because the new program ended. It's because it never ran to begin with.

Edit: the child process doesn't really die. The PID and environment remain unchanged, but the entire code and data are replaced with the exec'd process. You can count on not returning to the original child process, unless exec fails.

Nathan Fellman
I do that already in the else { } I just didn't posted the code... But isn't the status always going to be 0 because of the exit(0)??
Nazgulled
I think I got it now, thanks...
Nazgulled
One last thing, if execvp() returned -1, should I do exit(0) or should I pass some other value to the exit() call?
Nazgulled
Like exit(errno) is probably better, yes?
Nazgulled
@Nazgulled: the only standard return values for a process are 0/EXIT_SUCCESS and EXIT_FAILURE (stdlib.h). You can return other values but keep in mind that only the 8 least significant bits can be retrieved.
Bastien Léonard
What should I return in exit() then?
Nazgulled
@Nathan: the child process does not 'die' on execvp(); it changes from the original program to the new one, but the process ID is the same as before. Die is done by exit or a signal - continuing to run with a new executable is definitely not dying.
Jonathan Leffler
@Jonathan: you're right. I'll update the answer
Nathan Fellman
+1  A: 

From your question it's a little hard to figure out what you're asking. So I'll try to cover a couple of the related issues:

  • execvp() either does not return (on success), or it returns an error. Meaning your child code only need handle error conditions. Your child code should capture the result of execvp() and use that value in exit() as you suggested. Your child code should never return 0, since the only success means that the execvp worked and that processs will return 0 (or not).
  • The parent can obtain child info from waitpid() about it's exit status. There are several macros defined to pull info from the returned status parameter. Notable for your purpose are WIFEXITED to tell you if the child exited "normally", and WEXITSTATUS to get the child's status as passed to exit(). See the waitpid man page for other macros.
dwc
A: 

Use wait() or waitpid() in the parent process. An example here: http://stackoverflow.com/questions/742413/return-code-when-os-kills-your-process/747819#747819.

Also, when a child dies the SIGCHLD signal is sent to the parent process.

Bastien Léonard