LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   terminating zombie processes (forked) (https://www.linuxquestions.org/questions/programming-9/terminating-zombie-processes-forked-863355/)

KillerCode 02-17-2011 12:22 PM

terminating zombie processes (forked)
 
ive found this code on "Advanced Linux Programming - Chapter 3 : Processes" it should terminate fork()ed processes after they done their job
but it doesnt, as soon as the forked processes finishes its job and calls exit, the whole application restarts :/


here is the code
Code:

#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

sig_atomic_t child_exit_status;

void clean_up_child_process (int signal_number)
{
  /* Clean up the child process.  */
  int status;
  wait (&status);
  /* Store its exit status in a global variable.  */
  child_exit_status = status;
}

int main ()
{
  /* Handle SIGCHLD by calling clean_up_child_process.  */
  struct sigaction sigchld_action;
  memset (&sigchld_action, 0, sizeof (sigchld_action));
  sigchld_action.sa_handler = &clean_up_child_process;
  sigaction (SIGCHLD, &sigchld_action, NULL);
  /* Now do things, including forking a child process.  */
  /* ...  */
  return 0;
}

and thats how i fork processes
Code:

if (fork() == 0)
{
    /* Call the Function required here */
    rename("/home/killercode/data.zip", "/home/killercode/file.zip");
    exit(0);
}

thanks.

chymeira 02-17-2011 12:51 PM

Hey mate, I just tried your app and it works fine ...

Try this .... to make things clear

Code:

int main() {
      pid_t pid[10];
      int i, child_status;

      for(i = 0; i < 10; i++)
          if((pid[i] = fork()) == 0)
              exit(0);
      for(i = 0; i < 10; i++) {
          pid_t wpid = waitpid(pid[i], &child_status, 0);
          if(WIFEXITED(child_status))
              printf("Child %d terminated with exit status %d\n",
                              wpid, WEXITSTATUS(child_status));
          else
              printf("Child %d terminated abnormally\n", wpid);
      }

        return 0;
}

Hope it helps .

KillerCode 02-17-2011 01:04 PM

yea, but with ur method ill have to call the cleanup code reguraly, im trying to get the one i posted to work since the forked processes sends a SIGCHLD signal whenever it finishes working. so its not blocking any of the app functions.

thanks.

EDIT: this app should sleep for 100 seconds, but it doesnt :/
Code:

#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

sig_atomic_t child_exit_status;

void clean_up_child_process (int signal_number)
{
  /* Clean up the child process.  */
  int status;
  wait (&status);
  /* Store its exit status in a global variable.  */
  child_exit_status = status;
}

int main ()
{
  /* Handle SIGCHLD by calling clean_up_child_process.  */
  struct sigaction sigchld_action;
  memset (&sigchld_action, 0, sizeof (sigchld_action));
  sigchld_action.sa_handler = &clean_up_child_process;
  sigaction (SIGCHLD, &sigchld_action, NULL);
  if (fork() == 0)
  {
        exit(0);
  }
  sleep(100);
  return 0;
}


chymeira 02-17-2011 01:14 PM

Yes you are right , I just wanted to demonstrate the use of the macros WIFEXITED and EXITSTATUS for debugging your code.

Like I said , I ran your code and it works just fine on my system.

KillerCode 02-17-2011 01:24 PM

the last one i posted? does it sleep for 100 seconds? cause it exits right away from my terminal :S

z1p 02-17-2011 01:54 PM

Quote:

Originally Posted by KillerCode (Post 4261839)
yea, but with ur method ill have to call the cleanup code reguraly, im trying to get the one i posted to work since the forked processes sends a SIGCHLD signal whenever it finishes working. so its not blocking any of the app functions.

thanks.

EDIT: this app should sleep for 100 seconds, but it doesnt :/

That is because the sigchild signal interrupts the sleep call. Try something like the following to sleep for the full time.
Code:

sleeptime = 100;
while ((sleepTime = sleep(sleepTime)) > 0);

See the man page for sleep for more info on how it works.

KillerCode 02-17-2011 02:09 PM

its not just sleep, any function i do, such as receiving file from http server, it restarts the whole application as soon as the download (forked process) completes !!

z1p 02-17-2011 02:18 PM

I ran your test code replacing sleep with the while loop I provided and it sleeps the whole time.

What are you doing in the parent process? I assume you have a loop doing something? what is the exit condition of the loop? Other system calls are affected by signals and need to be 'restarted' after a signal occurs in a process.

KillerCode 02-17-2011 07:44 PM

even socket calls? like recv?

and yea, ive a loop in the forked process and a loop in the parent process....

z1p 02-17-2011 09:29 PM

Yes sys calls like recv will return on a signal.

See the man page (http://linux.die.net/man/3/recv), one of the possible errno value it sets is EINTR.

somethng like this handles it.

Code:

errno = 0
while (((cnt = recv(...)) < 0) && errno == EINTR))


KillerCode 02-17-2011 11:36 PM

ok, i can do something like that, one more question, is there is no other way to make it uninterrupted? maybe a something when assigning the signal handler? or there is no way to evade the interruption without modifiying recv()?

Bagration 02-18-2011 07:42 AM

Hello KillerCode,

I tested your original sleep(100)-Code. It works fine. Must really have to do something with your parents process.

Greetings Bernd

z1p 02-18-2011 10:13 AM

What I showed is a pretty standard way of dealing with it as it will work everywhere and always.

Take a look at the man page for signal (http://www.kernel.org/doc/man-pages/.../signal.7.html) for a info on signals and interruptable system calls. On linux you can possible use SA_RESTART with your signal handler, but it doesn't all interruptable system calls. You'll notice on the man page that SA_RESTART works for recv, depending on how it is called.


All times are GMT -5. The time now is 03:07 PM.