what's the relationship between exit(0) and zombie process - c

I found that it can't create a zombie process when I remove exit(0); from the child part. Can you tell me why?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
int main() {
if(!fork()) {
printf("child pid=%d\n", getpid());
exit(0);
}
sleep(20);
printf("parent pid=%d\n",getpid());
exit(0);
}

A zombie process is a dead child process that the parent process hasn’t checked on. In the original code, the child ends 20 seconds earlier than the parent, so it’s a zombie for 20 seconds. If you remove the first exit(0), they both stay alive for 20 seconds because in the child, control passes right out the bottom of the if block unless something stops it.
Thus, if you remove the child's exit() then not only is it unlikely to go zombie for an observable amount of time, but you should see it print a "parent pid" message in addition to its "child pid" message.

Related

Creating Zombie process in C (Linux) [duplicate]

This question already has answers here:
Create zombie process
(2 answers)
Closed 1 year ago.
my task is to create zombie process. My code looks like this:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
printf("error\n");
}
else if (pid == 0) {
printf("Child %d\n", getpid());
printf("Parents %d\n", getppid());
printf("Waiting for my Child to complete\n");
exit(0);
}
else {
sleep(5);
printf("Parent %d\n",getpid());
}
return 0;
}
When I gcc and execute the file with ./a.out I get the following output:
Child 25097
Parents 25096
Waiting for my child to complete
Parent 25096 ( a few seconds later)
My task is to create a zombie process and print out the exit-state of the child process while being in parent process. Everything is a bit confusing to me because its the first time for me using Linux and C.
Do you have some tips/ hints for me, how to solve the task? Cause I'm not sure if everything is right. I also tried playing with wait(), waitpid() and WEXITSSTATUS(), but I'm not sure about it. And I used the ps x command to check if there is a different output but I didn't notice any changes.
Thanks in advance :)
This code will successfully create a zombie process.
After the call to fork, the child prints a few lines and exits, while the parent sleeps for 5 seconds. This means you'll have a zombie process for about 5 seconds while the parent is sleeping.
When the sleep is done, the parent prints something and exits. Once the parent exits the child is inherited by the init process, which will wait for the child and make it's pid disappear fro the pid list.
You can also use wait in the parent process, in which case the child is a zombie up until the parent calls wait.

Why child process not getting exited before parent process calls wait() function?

I'm working on c program which uses fork() and wait() calls, firstly I created five child processes and then I called wait() for five times. Whenever I execute the program it prints the same child process id in the second for loop which is displayed from the first for loop. The child processes were never getting exited before the wait() function is getting called. Why is this happening? Why the cpid is always printing the exact child process id which were displayed before?
code :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main( )
{
int child_pids[5];
int i;
printf("PARENT ID: %d \n", getpid());
for(i=0;i<5;i++) {
if(fork()==0) {
printf("child(pid): %d of parent(pid): %d \n",getpid(),getppid());
exit(0);
}
}
for(i=0;i<5;i++) {
int cpid=wait(NULL);
printf("parent (pid): %d waited for child(pid): %d \n",getpid(),cpid);
}
return 0;
}
If there are any mistakes in my way of asking questions, please comment below
Upon exit, the child leaves an exit status that should be returned to the parent. So, when the child finishes it becomes a zombie.
Whenever the child exits or stops, the parent is sent a SIGCHLD signal.
The parent can use the system call wait() or waitpid() along with the macros WIFEXITED and WEXITSTATUS with it to learn about the status of its stopped child.
If the parent exits, than you can see your children still as zombie processes (unwaited children ).
wait() just tells you which child exited so you can get the exit code. If you have more children running, then of course, others could have terminated in the meantime as well.
If you don't care about the exit status, then wait() is just fine, but you still have to wait on all children you started.

re-parenting stopped process

How does re-parenting of stopped process heppens? Why does stopped process just terminates after re-parenting?
More precisely, suppose I have a code like this
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <stdio.h>
int main(void) {
pid_t child;
child = fork();
if (child == 0) {
int t = 0;
while (true) {
printf("%d. I'm %d, my parent is %d\n", t++, getpid(), getppid());
sleep(1);
}
} else {
printf("I'm the parent. My pid is %d\n", getpid());
printf("Starting to wait for 30 seconds\n");
sleep(30);
printf("Done waiting, aborting\n");
}
}
When I run this code the child process works and parent process just sleeps. After 30 seconds passed the parent process terminates and the child process now becomes a child of init and just continues running. Everything is normal.
But if I run this code and in first 30 seconds of it's execution I also run
kill -SIGSTOP <child_pid>
Then the child process stops (T state in ps xaf) and the parent process sleeps. After 30 second passed the parent process returns from sleep and just terminates (as it reached the end of main) but the child process instead of being re-parented to init in stopped state just terminates. I don't see it in ps xaf and if run lastcomm I see this output:
a.out F X equi pts/5 0.00 secs Wed Mar 16 17:44
Why is this happening that stopped process dies after re-parenting? Is it possible in linux to re-parrent stopped process?
From http://www.gnu.org/software/libc/manual/html_node/Job-Control-Signals.html
When a process in an orphaned process group (see Orphaned Process
Groups) receives a SIGTSTP, SIGTTIN, or SIGTTOU signal and does not
handle it, the process does not stop. Stopping the process would
probably not be very useful, since there is no shell program that will
notice it stop and allow the user to continue it. What happens instead
depends on the operating system you are using. Some systems may do
nothing; others may deliver another signal instead, such as SIGKILL or
SIGHUP. On GNU/Hurd systems, the process dies with SIGKILL; this
avoids the problem of many stopped, orphaned processes lying around
the system.
See also: What's the difference between SIGSTOP and SIGTSTP?

Linux /proc/PID dir of child stays alive after parent kills child

It seems that if I create a process, fork it and send a SIGHUP from the parent to the child, the child dies but it's "/proc/PID" dir doesn't dissappear until the parent also dies.
(See code below).
What is the right way to let the parent check if the child is dead ?
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
void testprocdir(pid_t pid) {
struct stat sb;
char path[1024];
sprintf(path,"/proc/%d",pid);
if(stat(path, &sb)==-1 && errno == ENOENT) {
printf("%s does not exist\n", path);
} else {
printf("%s exists\n", path);
}
}
int main(int argc,char **argv) {
pid_t parent,child;
parent=getpid();
printf("I am %d\n",parent);
child=fork();
switch(child) {
case -1:
printf("Forking failed\n");
return 2;
case 0:
parent=getppid();
child=getpid();
printf("I am the child (%d) and my parent is %d\n", child, parent);
while(1) { sleep(1); printf("I am the child and I have slept 1s\n");}
printf("This line should not be visible\n");
}
sleep(1); //make sure kid is in the while loop
printf("I am the parent (%d) and my kid is %d\n", parent, child);
kill(child,SIGHUP);
testprocdir(parent);
printf("Waiting 5s before testing if the procdir of the child (/proc/%d) is removed\n",child);
sleep(5);
testprocdir(child);
return 0;
}
You could use the wait family of system-calls.
fork returns the PID of the child process in the parent process, and 0 in the child process.
man waitpid should provide more than enough direction beyond that to call waitpid in the parent, allowing you to check that child process or all child processes ― including the ability to allow the parent to continue executing if the child is still alive or stop all execution in the parent until the child is dead.
I will start with some concepts:
The OS will keep a child process' entry in the process table (including exit status) around until the parent calls waitpid (or another wait-family function) or until the parent exits (at which point the status is collected by the init process). This is what a "zombie" process is: a process that has exited by is still resident in the process table for exactly this purpose. The process' entry in the table should go away after the first call to waitpid.
Also, from the man page :
A child that terminates, but has not been waited for becomes a "zombie". The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child.
So, by using the wait family of functions you can examine the status of child process.
There are some macros also that can be used with with wait family of functions to examine the status of child process like WEXITSTATUS, WIFSIGNALED, WIFEXITED etc .

Forking in a loop does not work as thought

I want to have the main process to run and create 4 subprocesses. Once they are created I want the main process to wait for them to finish.
This is my whole code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int i;
int childID;
int status;
for (i=0;i<4;i++){
childID=fork();
if (childID==0){
printf("[%d] I the child, will sleep\n", (int)getpid());
sleep(1);
}
}
if (!childID){
wait(&status);
printf("[%d] I the parent, have waited for my children!\n", (int)getpid());
}
return 0;
}
What I get instead is this:
..
[8508] I the child, will sleep
[8503] I the parent, have waited for my children!
[8511] I the child, will sleep
[8510] I the child, will sleep
[8509] I the child, will sleep
[8520] I the child, will sleep
[8511] I the parent, have waited for my children!
[8510] I the parent, have waited for my children!
(prompt stuck)
Why does the parent print out multiple times instead of once, in the end?
Is not the parent who writes multiple times, but the first 3 children. When you fork, the children gets an exact copy of the process including its address space, stack, registers, everything. That means that after the first fork both the parent and the new child will go through the for 3 more times creating 3 new childs. You should break out of the for when executing as the children for the desired effect:
if (childID==0){
printf("[%d] I the child, will sleep\n", (int)getpid());
sleep(1);
break;
}
Look at the pids of the prints. 8510 and 8511 are children, not the original parent. When you fork in the loop, the children are also in that loop. Try putting a break; after the sleep(1).
When you run the loop, once you fork, the child sleeps during the first iteration after it is forked off, but then it forks off more processes. Since childID is no longer 0 for those processes, the do not call wait and so they do not reap their children. This means that when all of the wait calls are completed you will still have processes running, so the terminal will hang.

Resources