defunct, what is it?

  I write a short program client and server. Client sends a number, server uses it to do something and sends the result to client. When the server receives a message, it forks a child to process it, and listens for another one. After processing the message, the child exits, but when I use ps to see the processes, I still see the ID of child and the word "defunct" behind. I don't know what it means? How can I solve it?
pttthaoAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rdelfinoCommented:

It means the process has exited and is just waiting for its parent process call wait() or waitpid().

If the parent process doesn't call wait() neither waitpid(), the  defunct process continue to exist until the parent process exits.

Below there 2 examples to deal with the defunct processes:

--------------8<------------

/* example 1 */
/* includes */


int main(int argc, char *argv[], char *arge[])
{
  pid_t pidDead;
  int status;

  /*
   
    initializtion
                         
  */
               
  for(;;)
  {
    do
    {
      pidDead = waitpid(-1, &status, WNOHANG);
      /*
       pidDead is a dead child process pid
       status stores the exit code, and the reason why the child
       process exited.
      */
    }
    while (pidDead != -1);

    s = accept(listenSocket, NULL, NULL);
    if (!fork())
    {
      /* do whatever you need */
      exit(0);
    }
  }
}

--------------8<------------

/* example 2 */
/* includes */

void deadChildHandler(int sig);

int main(int argc, char *argv[], char *arge[])
{

  /*
   
    initializtion
                         
  */
  struct sigaction sigAct;
             
  sigfillset(&sigAct.sa_mask);
  sigAct.sa_flags = 0;
  sigAct.sa_handler = deadChildHandler;
  sigaction(SIGCLD, &sigAct, NULL);
               
  for(;;)
  {
    s = accept(listenSocket, NULL, NULL);
    if (!fork())
    {
      /* do whatever you need */
      exit(0);
    }
  }
}

void deadChildHandler(int sig)
{
  pid_t pidDead;
  int status;
  do
  {
    pidDead = waitpid(-1, &status, WNOHANG);
    /*
     pidDead is a dead child process pid
     status stores the exit code, and the reason why the child
     process exited.
    */
  }
  while (pidDead != -1);
 }

--------------8<--------------

Example 1 removes all defunct process the parent owns before each request your server answers by calling waitpid() before
accept().

Example 2 uses a signal handler to deal with the defuncts.
Every time a child process dies, its parent receives a SIGCLD
signal. The default disposition for SIGCLD is SIGCLD to be
ignored. In the example above, a signal handler for
SIGCLD is set, so that the parent process is able to know
when a child has died.

In the signal handler function (deadChidHandler()), waitpid() is
called untill all defunct process the parent has generated are
removed from the process table.

If you are using Solaris, you'll find further information in

man waitpid
man fork
man -s2 wait
man sigaction
man signal

I hope it helps

Reginaldo
0
rdelfinoCommented:

It means the process has exited and is just waiting for its parent process call wait() or waitpid().

If the parent process doesn't call wait() neither waitpid(), the  defunct process continue to exist until the parent process exits.

Below there 2 examples to deal with the defunct processes:

--------------8<------------

/* example 1 */
/* includes */


int main(int argc, char *argv[], char *arge[])
{
  pid_t pidDead;
  int status;

  /*
   
    initializtion
                         
  */
               
  for(;;)
  {
    do
    {
      pidDead = waitpid(-1, &status, WNOHANG);
      /*
       pidDead is a dead child process pid
       status stores the exit code, and the reason why the child
       process exited.
      */
    }
    while (pidDead != -1);

    s = accept(listenSocket, NULL, NULL);
    if (!fork())
    {
      /* do whatever you need */
      exit(0);
    }
  }
}

--------------8<------------

/* example 2 */
/* includes */

void deadChildHandler(int sig);

int main(int argc, char *argv[], char *arge[])
{

  /*
   
    initializtion
                         
  */
  struct sigaction sigAct;
             
  sigfillset(&sigAct.sa_mask);
  sigAct.sa_flags = 0;
  sigAct.sa_handler = deadChildHandler;
  sigaction(SIGCLD, &sigAct, NULL);
               
  for(;;)
  {
    s = accept(listenSocket, NULL, NULL);
    if (!fork())
    {
      /* do whatever you need */
      exit(0);
    }
  }
}

void deadChildHandler(int sig)
{
  pid_t pidDead;
  int status;
  do
  {
    pidDead = waitpid(-1, &status, WNOHANG);
    /*
     pidDead is a dead child process pid
     status stores the exit code, and the reason why the child
     process exited.
    */
  }
  while (pidDead != -1);
 }

--------------8<--------------

Example 1 removes all defunct process the parent owns before each request your server answers by calling waitpid() before
accept().

Example 2 uses a signal handler to deal with the defuncts.
Every time a child process dies, its parent receives a SIGCLD
signal. The default disposition for SIGCLD is SIGCLD to be
ignored. In the example above, a signal handler for
SIGCLD is set, so that the parent process is able to know
when a child has died.

In the signal handler function (deadChidHandler()), waitpid() is
called untill all defunct process the parent has generated are
removed from the process table.

If you are using Solaris, you'll find further information in

man waitpid
man fork
man -s2 wait
man sigaction
man signal

I hope it helps

Reginaldo
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
bertvermeerbergenCommented:
It is all what is left over from your child process after it exits, an entry in the process table that allows the parent process to collect the exit code from its child.  Another name for these entries without a process is 'zombie'.
The parent process should do one of the following:
1) Wait for its child(ren) to exit, using the wait() system call somewhere in your code, to collect the exit code and allow the process entry (zombie) to be dead and burried.
2) Setup an handler for the SIGCHILD signal to call wait(), using the signal() or sigaction() calls.
3) Let the OS known that the parent is not interested in the exit codes from its child(ren).  This is done by setting the signal handler for SIGCHILD to SIG_IGN.

Bert
0
pttthaoAuthor Commented:
Thanks for your helping
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.