How to Avoid zombie Processes

Source: Internet
Author: User

In the fork ()/execve () process, assume that the parent process still exists at the end of the Child process, and the parent process fork () has not installed the sigchld signal processing function to call waitpid () when the sub-process ends and the signal is not explicitly ignored, the sub-process becomes a zombie and cannot end normally. In this case, even the root identity kill-9 cannot kill the zombie process. The remedy is to kill the parent process of the zombie process (the parent process of the zombie process must exist). The zombie process becomes an "orphan process" and passes the process init to process 1, init is always responsible for cleaning up zombie processes.

How to clear zombie processes:
1. Rewrite the parent process and send it to the dead after the child process dies. The specific method is to take over the sigchld signal. After a child process dies, it sends a sigchld signal to the parent process. After receiving the signal, the parent process executes the waitpid () function to collect the child process. This is based on the principle that even if the parent process does not call wait, the kernel will send sigchld messages to it, even though the default processing is ignored. If you want to respond to this message, you can set a processing function.
2. Kill the parent process. After the death of the parent process, the zombie process becomes an "orphan process". After it passes through to the INIT process on process 1, init will always be responsible for cleaning up the zombie process. All the zombie processes it generates will also disappear.
3. Call fork twice.

How to generate a zombie process:

# Include <sys/types. h>
# Include <unistd. h>
# Include <stdio. h>
# Include <stdlib. h>

Int main (INT argc, char ** argv)
{
If (0 = fork ()){
Printf ("in the child process: % d \ n", getpid ());
} Else {
Printf ("in the parent process: % d \ n", getpid ());
Sleep (10 );
Exit (0 );
}
Printf ("PID: % d \ n", getpid ());
Return 0;
}

How to avoid:

If the call is successful, the cleared sub-process ID is returned. If an error occurs in the call,-1 is returned. Parent process callwaitOrwaitpidMay be:

  • Blocking (if all its sub-processes are still running ).

  • The process termination information is returned immediately (if a child process has been terminated, it is waiting for the parent process to read its termination information ).

  • Returns an error immediately (if it does not have any sub-processes ).

The difference between the two functions is:

  • If all child processes of the parent process are still runningwaitWill block the parent process and callwaitpidIfoptionsParameterWNOHANGThe parent process is not blocked and 0 is returned immediately.

  • waitWait for the first child process to terminate, andwaitpidYou can usepidThe parameter specifies the child process to wait.

Visible, calledwaitAndwaitpidNot only can the termination information of the child process be obtained, but also the parent process can be blocked and wait for the child process to terminate.

# Include <sys/types. h> # include <sys/Wait. h> # include <unistd. h> # include <stdio. h> # include <stdlib. h> int main (void) {pid_t PID; pid = fork (); If (PID <0) {perror ("fork failed"); exit (1 );} if (pid = 0) {int I; for (I = 3; I> 0; I --) {printf ("this is the child \ n "); sleep (1) ;}exit (3) ;}else {int stat_val; waitpid (PID, & stat_val, 0); If (wifexited (stat_val )) printf ("Child exited with code % d \ n", wexitstatus (stat_val); else if (wifsignaled (stat_val) printf ("Child terminated abnormally, signal % d \ n ", wtermsig (stat_val);} return 0;} 2 processing signal: # include <sys/types. h> # include <unistd. h> # include <stdio. h> # include <stdlib. h> # include <sys/Wait. h>

Void proc_child (INT signo)
{
Int pid =-1;
Int Stat;
PID = waitpid (-1, & stat, wnohang );
}

Int main (INT argc, char ** argv)
{
Signal (sigchld, proc_child );
If (0 = fork ()){
Printf ("in the child process: % d \ n", getpid ());
} Else {
Printf ("in the parent process: % d \ n", getpid ());
Sleep (10 );
Exit (0 );
}
Printf ("PID: % d \ n", getpid ());
Return 0;
}

3 ignore signal int main (INT argc, char ** argv) {signal (sigchld, sig_ign); // Add this sentence to ignore sigchld signal if (0 = fork ()) {printf ("in the child process: % d \ n", getpid ();} else {printf ("in the parent process: % d \ n ", getpid (); sleep (10); exit (0);} printf ("PID: % d \ n", getpid (); Return 0 ;} 4. Fork on apue twice:

Fork two times in the prevention of death, it is because the son process first exited, the son process was taken over by init, in fact, with the initial parent process out of the relationship, will not be frozen.

# Include <stdio. h> # include <sys/Wait. h> # include <sys/types. h> # include <unistd. h> int main (void) {pid_t PID; If (pid = fork () <0) {fprintf (stderr, "fork error! \ N "); exit (-1);} else if (pid = 0)/* First child */{If (pid = fork () <0) {fprintf (stderr, "fork error! \ N "); exit (-1);} else if (pid> 0) Exit (0 ); /* parent from second fork = first child * // ** we're the second child; our parent becomes init as soon * as our real parent callexit () in the statement above. * Here's where we 'd continue executing, knowing that when * we're done, init will reap our status. */sleep (2); printf ("second child, parent pid = % d \ n", getppid (); exit (0);} If (waitpid (PID, Null, 0 )! = PID)/* Wait for first child */{fprintf (stderr, "waitpid error! \ N "); exit (-1);}/** we're re the parent (the original process); we continue executing, * knowing that we're not the parent of the second child. */exit (0);} 5 static voidsig_child () {waitpid (-1, null, 0);} [...] the signal (sigchld, sig_child) sig_child function has a problem. This function is used to call sig_child every time a process exits. sig_child calls waitpid to process an exited sub-process. But if the program is in sig_child and another sub-process exits, what should I do? The processing method should be that there is no other sig_child response, so two sub-processes exit, but sig_child can only process one, therefore, an exited sub-process becomes a zombie process.

Change sig_child:
Static void
Sig_child ()
{
While (waitpid (-1, null, 0)> 0 );
}

In this case, if the program is in sig_child, then another n sub-processes exit. Because while is used, sig_child will "break all" the sub-processes that exit ".

This is a method to handle zombie processes, and there are two other methods:
Signal (sigchld, sig_ign );
Ignore the sigchld signal. The parent process does not need to be processed. Instead, it directly pushes the exited child process to the INIT process for processing.

Struct sigaction SA;
SA. sa_handler = sig_ign;
SA. sa_flags = sa_nocldwait;
Sigemptyset (& SA. sa_mask );
If (sigaction (sigchld, & SA, null) <0 ){
Exit (-1 );
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.