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

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);
}

Related

Wait for all child processes in fork chain

i want one parent process to create 10 child processes, but how can i make the parent process to wait for all child processes?
i have this given code in C
for(int cnt = 1; cnt<=10; cnt++) {
switch ( pid = fork() ) {
case -1:
perror("error");
break;
case 0:
printf("%d: child process, my PID=%d and PPID=%d\n", cnt, getpid(), getppid() );
sleep(10);
exit(0);
break;
default:
printf("%d: parent process, my PID=%d and PPID=%d\n", cnt, getpid(), getppid() );
sleep(10);
}
}
}
i tried with wait and waitpid in the default part, but it seems that the parent process only waits for the next child process to exit.
how can i make it wait for all 10 child processes to exit?
You have to loop over the child processes and, if you want, get your status.
Like this:
int i, pid, status;
for (i=0; i<10N; i++) {
pid=wait(&status);
printf("Arrived child with pid %d - status %d\n", pid, status);
}

Where did the zombie process go?

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().

why does the parent pid return a different value than getpid()?

According to the man page
getpid() returns the process ID (PID) of the calling process.
In the following code why does the parent pid return a different value than getpid() ?
Isn't the main process the same as the parent process?
And why do I get different outputs when run on a different system?
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
printf("getpid = %d \n", (int)getpid());
pid_t pid = fork();
printf("fork returned %d \n", (int)pid);
switch (pid)
{
case -1:
perror("fork failed");
break;
case 0:
printf("I am a child with pid = %d\n", (int)pid);
break;
default:
printf("I am a parent with pid = %d\n", (int)pid);
break;
}
return 0;
}
output when i run :
getpid = 8208
fork returned 8209
I am a parent with pid = 8209
fork returned 0
I am a child with pid = 0
output when run on a different pc:
getpid = 2522
fork returned 2523
I am a parent with pid = 2522
fork returned 0
I am a child with pid = 2523
Yes, the parent process and main process are the same thing.
This snippet of your code should give you a clue about the solution:
switch (pid) {
/* ... */
case 0:
printf("I am a child with pid = %d\n", (int)pid);
break;
This effectively says "if pid is zero then the child pid is always zero". This obviously cannot be true, so it is your interpretation of fork()'s return value that is incorrect.
The man page states:
Upon successful completion, fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent process.
So the variable pid in the parent process is the pid of the child, NOT the parent's own pid.
In the child process, you would need to call getpid() after fork() to get the child's own pid.
fork duplicates a process and after the fork, they both run in parallel. To tell the program whether it is a child or the parent, it returns 0 for the child and the PID of the child process is returned in the parent.
So after the fork, you must call getpid() for both parent and child, in your code that would be:
pid_t thispid= getpid();
switch (pid)
{
case -1:
perror("fork failed");
break;
case 0:
printf("I am a child with pid = %d\n", (int)thispid);
break;
default:
printf("I am a parent with pid = %d\n", (int)thispid);
break;
}

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.

Resources