How do you kill zombie process using wait()
Asked Answered
A

4

6

I have this code that requires a parent to fork 3 children.

  • How do you know (and) where to put the "wait()" statement to kill
    zombie processes?

  • What is the command to view zombie processes if you have Linux virtual box?

    main(){
    
     pid_t child;
     printf("-----------------------------------\n");
     about("Parent");
     printf("Now ..  Forking !!\n");
     child = fork();
     int i=0;
    
     for (i=0; i<3; i++){
        if (child < 0) {
            perror ("Unable to fork");
            break;
        } 
        else if (child == 0){
            printf ("creating child #%d\n", (i+1));
            about ("Child");
            break;
        }
    
        else{
            child = fork();
        }
      } 
    }       
    
    void about(char * msg){
    
     pid_t me;
     pid_t oldone;
    
     me = getpid();
     oldone = getppid();
    
     printf("***[%s] PID = %d   PPID = %d.\n", msg, me, oldone);
    
    }
    
Angara answered 11/2, 2015 at 15:2 Comment(1)
If I were to assume - I would put wait(3) after the child=fork() in the else statement. Although I'm not fluent with zombie processes or linux, so I'm not too sure how view the zombie processesAngara
V
12

How do you know (and) where to put the "wait()" statement to kill zombie processes?

If your parent spawns only a small, fixed number of children; does not care when or whether they stop, resume, or finish; and itself exits quickly, then you do not need to use wait() or waitpid() to clean up the child processes. The init process (pid 1) takes responsibility for orphaned child processes, and will clean them up when they finish.

Under any other circumstances, however, you must wait() for child processes. Doing so frees up resources, ensures that the child has finished, and allows you to obtain the child's exit status. Via waitpid() you can also be notified when a child is stopped or resumed by a signal, if you so wish.

As for where to perform the wait,

  • You must ensure that only the parent wait()s.
  • You should wait at or before the earliest point where you need the child to have finished (but not before forking), OR
  • if you don't care when or whether the child finishes, but you need to clean up resources, then you can periodically call waitpid(-1, NULL, WNOHANG) to collect a zombie child if there is one, without blocking if there isn't any.

In particular, you must not wait() (unconditionally) immediately after fork()ing because parent and child run the same code. You must use the return value of fork() to determine whether you are in the child (return value == 0), or in the parent (any other return value). Furthermore, the parent must wait() only if forking was successful, in which case fork() returns the child's pid, which is always greater than zero. A return value less than zero indicates failure to fork.

Your program doesn't really need to wait() because it spawns exactly four (not three) children, then exits. However, if you wanted the parent to have at most one live child at any time, then you could write it like this:

int main() {
    pid_t child;
    int i;

    printf("-----------------------------------\n");
    about("Parent");

    for (i = 0; i < 3; i++) {
        printf("Now ..  Forking !!\n");
        child = fork();

        if (child < 0) {
            perror ("Unable to fork");
            break;
        } else if (child == 0) {
            printf ("In child #%d\n", (i+1));
            about ("Child");
            break;
        } else {
            /* in parent */
            if (waitpid(child, NULL, 0) < 0) {
                perror("Failed to collect child process");
                break;
            }
        }
    }

    return 0;
}

If the parent exits before one or more of its children, which can happen if it does not wait, then the child will thereafter see its parent process being pid 1.

Others have already answered how to get a zombie process list via th ps command. You may also be able to see zombies via top. With your original code you are unlikely to catch a glimpse of zombies, however, because the parent process exits very quickly, and init will then clean up the zombies it leaves behind.

Voss answered 11/2, 2015 at 16:36 Comment(0)
C
1

How do you know (and) where to put the "wait()" statement to kill zombie processes?

You can use wait() anywhere in the parent process, and when the child process terminates it'll be removed from the system. Where to put it is up to you, in your specific case you probably want to put it immediately after the child = fork(); line so that the parent process won't resume its execution until its child has exited.

What is the command to view zombie processes if you have Linux virtual box?

You can use the ps aux command to view all processes in the system (including zombie processes), and the STAT column will be equal to Z if the process is a zombie. An example output would be:

USER      PID    %CPU %MEM VSZ  RSS TTY      STAT START   TIME COMMAND
daniel    1000   0.0  0.0  0    0   ??       Z    17:15   0:00 command
Cooncan answered 11/2, 2015 at 15:16 Comment(3)
Thank you for getting back to me. While testing this without a wait(), when spamming compile, I see that sometimes I get a 1 for PPID instead of the PID of the parent. With the wait(5) inside the parent function, I do not see any. Does that mean having the wait(5) inside the function is getting rid of zombie processes?Angara
Also, when I type ps aux, I end up going to line(?) 26433 tc. It just spams tc all the way down so I'm not sure where to look.Angara
Assuming you have zombie processes, run ps aux | grep Z to view just the lines containing Z (if your program has finished its execution then this won't show you anything relevant, as all the zombie children have been removed from the system). As for your first issue, what's happening is that your child process is running after the parent process has exited, so its parent is now the init process which has pid == 1. By calling wait you're preventing the parent process from exiting until at least one of its children has finished its execution.Cooncan
P
0

How do you know (and) where to put the "wait()" statement to kill zombie processes?

You can register a signal handler for SIGCHLD that sets a global volatile sig_atomic_t flag = 0 variable to 1. Then, at some convenient place in your program, test whether flag is set to 1, and, if so, set it back to 0 and afterwards (for otherwise you might miss a signal) call waitpid(-1, NULL, WNOHANG) in a loop until it tells you that no more processes are to be waited for. Note that the signal will interrupt system calls with EINTR, which is a good condition to check for the value of flag. If you use an indefinitely blocking system call like select(), you might want to specify a timeout after which you check for flag, since otherwise you might miss a signal that was raised after your last waitpid() call but before entering the indefinitely blocking system call. An alternative to this kludge is to use pselect().

Parke answered 8/7, 2017 at 20:46 Comment(0)
C
0

Use:

ps -e -opid,ppid,pgid,stat,etime,cmd | grep defunct

to see your zombies, also the ppid and pgid to see the parent ID and process group ID. The etime to see the elapsed (cpu) time your zombie has been alive. The parent ID is useful to send custom signals to the parent process.

If the parent process is right coded to catch and handle the SIGCHLD signal, and to what expected (i.e., wait/reap the zombies), then you can submit:

kill -CHLD <parent_pid>

to tell the parent to reap all their zombies.

Cathey answered 18/10, 2020 at 14:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.