Where did the zombie process go? - c

int main() {
pid_t pid;
printf("Parent: %d\n", getpid());
pid = fork();
if (pid == -1) {
perror("fork");
goto clean_up;
} else if (pid > 0) {
sleep(3);
} else {
printf("Child Parent: %d\n", getppid());
printf("Child: %d\n", getpid());
printf("Exiting...\n");
}
clean_up:
return 0;
}
I wanted to create zombie process on purpose (of course for experimenting/learning). After the child exits, the parent doesn't wait()s for the child. So, I'm expecting zombie to show up, in ps -ef | grep zombie.o. But for some reason it is not showing up. What could be the possible reasons?

When the parent exits, all its children (alive or zombie) are assigned PID 1 as their new parent. See the _exit(2) man page: " any children of the process are inherited by process 1".
PID 1 is normally the init daemon, and if it's working properly then it should always wait() for its children. So zombie children will be reaped immediately, and children that are still running will be reaped as soon as they exit.
If you want to create a long-lived zombie, the parent needs to remain alive but not calling wait().

Related

kill(pid,SIGTERM) terminates child process, although pid is of parent

I'm learning about process allocation.
Take this code block for example:
int main(){
pid_t pid = fork();
if(pid == 0){
while(1)
printf("Child ");
} else {
for(int i = 0; i<1000;i++)
printf("Parent ");
kill(pid,SIGTERM);
printf("\n%d \n ", pid);
}
}
pid = 0 is the child process, pid > 0 is the parent process. kill(pid,SIGTERM) is executed by the parent with it's own pid, yet it kills the child and not itself. Why?
As #Siguza mentioned in the comments, you should re-read the documentation of fork. fork returns a positive value of pid to the parent process. That value is the PID of the child process. Therefore, kill(pid, SIGTERM) sends the signal to the child and not the parent.

fork() and parent/child process ids

I am a bit confused about why the child process in the following two programs is showing different parents ids.
First program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
pid = getpid();
ppid = getppid();
printf ("fpid is %d\n", fpid);
sleep(5);
if (fpid > 0){
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is 53560
fpid is 0
This is Parent. My pid 53559. My parent's pid 44632
MacBook-Pro:~/Desktop/$
This is Child. My pid 53560. My parent's pid 53559
Second program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
printf ("fpid is is %d\n", fpid);
sleep(5);
if (fpid > 0){
pid = getpid();
ppid = getppid();
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
pid = getpid();
ppid = getppid();
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is is 53635
fpid is is 0
This is Parent. My pid 53634. My parent's pid 44632
MacBook-Pro:~/Desktop$
This is Child. My pid 53635. My parent's pid 1
I understand that process 1 is the process that takes over as a parent once the original parent terminates. I guess what I want to know is: isn't the parent process being finished before the child process can process its printf in both cases? Shouldn't the outputs be the same?
Since parent and child processes run concurrently, the order of execution depends on runtime. One of them can finish earlier. When parent finishes before child reaches its getppid(), child process would be adopted by init. Hence the parent id 1.
To see child's actual parent process id:
Let the parent wait for its child termination using wait() or waitpid(), or
Let parent sleep for some perceivable amount like sleep(120) after 'This is parent' printf().
isn't the parent process being finished before the child process can process it's printf in both cases?
Very likely so, but not absolutely certain. You cannot ensure that by sleep()ing for any length of time.
Shouldn't the outputs be the same?
They could be the same, but they are unlikely to be. It's important to note when in each program getppid() is called. The parent process ID reported is the one that applied at the time of the call; it is not necessarily still applicable later, when the value is printed.

Create multiple child processes in UNIX

I want to write an UNIX program that creates N child processes, so that the first process creates one child process, then this child creates only one process that is its child, then the child of the child creates another child etc.
Here's my code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int N=3;
int i=0;
printf("Creating %d children\n", N);
printf("PARENT PROCESS\nMy pid is:%d \n",getpid() );
for(i=0;i<N;i++)
{
pid_t pid=fork();
if(pid < 0)
{
perror("Fork error\n");
return 1;
}
else if (pid==0) /* child */
{
printf("CHILD My pid is:%d my parent pid is %d\n",getpid(), getppid() );
}
else /* parrent */
{
exit(0);
}
}
return 0;
}
The output that I expect is in the form:
Creating 3 children
PARENT PROCESS
My pid is 1234
CHILD My pid is 4567 my parent pid is 1234
CHILD My pid is 3528 my parent pid is 4567
CHILD My pid is 5735 my parent pid is 3528
The output I get in the terminal is
Creating 3 children
PARENT PROCESS
My pid is:564
CHILD My pid is:5036 my parent pid is 564
User#User-PC ~
$ CHILD My pid is:4804 my parent pid is 1
CHILD My pid is:6412 my parent pid is 4804
The problem is that the program doesn't seem to terminate. I should use Ctrl+C to get out of the terminal, which is not normal. Can you help me to fix this issue?
The children die when the parent dies.
In your case the parent exits before all the children have been created.
Try waiting for the children before exiting:
else /* parrent */
{
int returnStatus;
waitpid(pid, &returnStatus, 0); // Parent process waits for child to terminate.
exit(0);
}
try to wait the process with wait(NULL);
pid_t child = fork();
if (child == -1)
{
puts("error");
exit(0);
}
else if (child == 0)
{
// your action
}
else
{
wait(&child);
exit(0);
}
so your father will wait the child process to exit
The proposed cure is correct, but the reason stated is wrong. Children do not die with the parent. The line
CHILD My pid is:4804 my parent pid is 1
clearly indicates that by the time child called getppid() its parent is already dead, and the child has been reparented to init (pid 1).
The real problem is that after the child prints its message, it continues to execute the loop, producing more children, making your program into a fork bomb.

c fork's child ppid does not match parent's pid

I'm totally new to C.
I tried the following code, expecting that the child's ppid would match the parent's pid, but this is not the case.
int main() {
int pid;
printf("I'm process with pid=%d\n", getpid());
switch (pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
printf("I'm the child process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
default:
printf("I'm the parent process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
}
exit(0);
}
> gcc -o fork fork.c
> ./fork
I'm process with pid=16907
I'm the parent process: pid=16907, ppid=6604
I'm the child process: pid=16908, ppid=1 // <-- expected ppid=16907, why 1?
>
What did I do wrong ?
It is likely the parent process has already exited and no longer exists. You could try some delay in the parent.
'init' which is the root process running in a linux system has pid 1 .
When a process's parent gets terminated before itself(i.e. the child) , the child becomes an 'orphan' process and is taken up by the root process or the process just above the hierarchy of the process which created it(parent process) .
Hence , here it is taken up by and executed under init which has pid = 1 .
So, delay your parent process for solution.
Like others have mentioned, looks like the parent process has terminated while the child process is still under execution making it(the child process) an orphan. Adding delay before exiting may work.
But an elegant way of doing it is, the parent process has to wait till the child process terminates.
This can be achieved by calling waitpid() with the pid of the child (the value returned by fork() ). When the control comes out of this function, you can be sure that the child process has terminated. Also, waitpid() returns the status of the process termination. Based on the status that it returns, you can get to know the normal/abnormal child termination.
Here is the code that does it:
int main() {
int pid;
int status = 0;
printf("I'm process with pid=%d\n", getpid());
switch (pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
printf("I'm the child process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
default:
waitpid(pid, &status, 0);
if(WIFEXITED(status)
{
printf("Normal termination of child process %d\n", pid);
}
else
{
printf("Abormal termination of child process %d\n", pid);
}
printf("I'm the parent process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
}
exit(0);
}

forking and pid

The code:
int main(void)
{
printf("pid: %d\n", getpid());
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed!");
exit(-1);
} else if (pid == 0) {
execv("sum", argv);
} else {
printf(" pid: %d\n", pid);
wait(NULL);
}
}
The output:
pid: 280
pid: 281
The question:
Why are the two pid's different. I thought they should be the same because the parent is what is executing in the else block and the parent is what is executing before the fork so they should be the same, no?
RETURN VALUE
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
So, in the parent process, fork() returns the pid of the child process that was created.
I won't repeat nos's answer, as he's entirely correct. But I'd point out that any program can retrieve it's own PID with the getpid system call. So there's no reason for the fork to return you own PID. Instead, you may want to know the PID of the process you just forked off, which may be difficult to obtain if it wasn't returned (to the parent) by fork.

Resources