简体   繁体   中英

Why does a process create a zombie if execv fails, but not if execv is successful and terminates?

So I am confused by the behavior of my C program. I am using the construct,

int pid = fork();
if (pid == 0) {
    if(file_upload_script_path) {
        rc = execv(file_upload_script_path, args);
        if(rc == -1) {   
            printf("Error has occured when starting file_upload.exp!\n");
            exit(0);
        }
    } else {   
        printf("Error with memory allocation!\n");
    }
}
else {
    printf("pid=%d\n", pid);
}

To fork the process and run a script for doing file upload. The script will by itself terminate safely, either by finishing the upload or failing.

Now, there was a problem with the script path, causing execv to fail. Here I noted the child process will terminate successfully if execv finishes, but in case it fails (r==-1) and I exit the process, it will become a zombie. Anyone knows why this happens?

Note here, I know why the child-process becomes a zombie. What I am confused about is why the process not becomes a zombie if execv works.

EDIT:

I got a question about errno and the cause of the error. The cause of the error is known. There were a problem with the build process, so the path of the script were another than expected.

However, this may happen again and I want to make sure my program does not start spawning zombies when it does. The behavoir where zombies are created in some situations and not others are very confusing.

BR Patrik

If you don't want to create zombies, your program has to reap zombie processes no matter if they call execv or not call it or no matter if the execv call succeeds. To reap zombie processes "automagically" handle SIGCHLD signal:

void handle_sigchld(int sig) {
    int saved_errno = errno;
    while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {}
    errno = saved_errno;
}

int main() {
    signal(SIGCHLD, handle_sigchld);
    // rest of your program....
}

Inspired (no... ripped off) from: this link .

Or maybe you want only to reap only this specified child, because later you want to call fork() and handle childs return value. Then pass the returned pid from fork() in your parent to the signal handler and wait on this pid in sigchld if needed (with some checking, ex. if the pid already finished then ignore future SIGCHLD etc...).

In this scenario, when the execv fails, the child process is killed. The fun part, I think is what happens when you call exec family of functions.

The exec family of functions replaces the current image of the process with the new image of the binary you are about to exec.

So, whatever code was will not remain - and the error in your script would cause its death.

Here, the parent needs to listen on the death of the child process using wait flavour of functions (read: waitpid).

When you say that there's problem in the script, it means that the execv actually succeeded in creating the new image; but the latter failed of its own accord.

This is what I think is happening...

If the printf of if (rc==-1) is being executed, then perhaps changing exit(0) to _exit(0) should take care of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM