parent process that calls waitpid() is unable to find its child - c

I am trying to better understand fork(), waitpid() and child/parent processes, however there are some strange behaviors I have encountered with the following code:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void){ // Main
int status;
pid_t wPID, cPID;
printf("[%i] Hi I am the parent and I am about to create a child...\n", getpid());
fflush(0);
pid_t childPID = fork();
if (childPID >= 0){
if(childPID == 0){ //child process
cPID = getpid();
printf("[%i] %i\n", getpid(), cPID );
printf("[%i] Hi, I am the child process...\n", getpid() );
sleep(1);
for(int i = 0; i<3; i++){
printf("[%i] %i\n", getpid(), i);
}
exit(0);
}
else{ //parent
printf("[%i] %i\n", getpid(), cPID );
wPID = waitpid(cPID, &status, 0);
printf("[%i] value returned by waitpid: %i\n", getpid(), wPID);
if (WIFEXITED(status))
printf("[%i] child exited, status=%d\n", getpid(), WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("[%i] child killed (signal %d)\n", getpid(), WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("[%i] child stopped (signal %d)\n", getpid(), WSTOPSIG(status));
else /* Non-standard case -- may never happen */
printf("Unexpected status (0x%x)\n", status);
return 0;
}
}
else{
printf("\n Fork failed, quitting!\n");
return 2; // error
}
}
console output:
$ ./waitpidexample
[6103] Hi I am the parent and I am about to create a child...
Error: No child processes
[6103] 1540418008
[6103] value returned by waitpid: -1
[6103] child killed (signal 54)
[6104] 6285
[6104] Hi, I am the child process...
[6104] 0
[6104] 1
[6104] 2
I believe my issue is in the cPID variable being used in waitpid()...
there is some sort of scope issue happening here, as it evaluates to different values in the child / parent.
How am I supposed to get the correct child process id for use in waitpid()?
Why is the code after my waitpid() being executed before the code in the child process?

cPID is only changed in the child process. When you call fork, a complete copy is made (functionally, in reality until something is changed, the memory is shared). This means that when cPID is written in the child (first branch) the parent does not see it. Change the references to cPID in the parent (second branch) to childPID (assigned from fork()):
else{ //parent
printf("[%i] %i\n", getpid(), childPID );
wPID = waitpid(childPID, &status, 0);
printf("[%i] value returned by waitpid: %i\n", getpid(), wPID);
if (WIFEXITED(status))
printf("[%i] child exited, status=%d\n", getpid(), WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("[%i] child killed (signal %d)\n", getpid(), WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("[%i] child stopped (signal %d)\n", getpid(), WSTOPSIG(status));
else /* Non-standard case -- may never happen */
printf("Unexpected status (0x%x)\n", status);
return 0;
}
Also, I recommend using braces after all your if statements
Run Order
fork() does not define which process gets run first, just that there is now a child process (in which it returns 0) and a parent process (in which it returns the child's PID). The child process will be identical to the parent, except for the return value of fork(). Sometimes, the parent goes first, sometimes the child does. It is non-deterministic.

In the parent process, cPID is never initialized. The variables in the parent and child are separate from each other, so a variable change in the child is not visible in the parent and vice versa.
The parent already has the child pid in childPID, so use that instead.
printf("[%i] %i\n", getpid(), childPID );
wPID = waitpid(childPID, &status, 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);
}

Parent/Child process print

I'm writing a C program that creates a child process. After creating the child process, the parent process should ouput two messages: "I am the parent" then it should print "The parent is done". Same for child process "I am child" and "The child is done". However I want to make sure, the second message of the child is always done before the second message of the parent. How can I achieve to print "The child is done" and "The parent is done" rather than printing their pid?
#include <unistd.h>
#include <stdio.h>
main()
{
int pid, stat_loc;
printf("\nmy pid = %d\n", getpid());
pid = fork();
if (pid == -1)
perror("error in fork");
else if (pid ==0 )
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
}
else
{
printf("\nI am the parent process, my pid = %d\n\n", getpid());
sleep(2);
}
printf("\nThe %d is done\n\n", getpid());
}
You could have a flag variable, that is set in the parent, but then the child clears it. Then simply check for that for the last output.
Something like
int is_parent = 1; // Important to create and initialize before the fork
pid = fork();
if (pid == -1) { ... }
if (pid == 0)
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
in_parent = 0; // We're not in the parent anymore
}
else { ... }
printf("\nThe %s is done\n\n", is_parent ? "parent" : child");
Call wait(2) in the parent process for the child to complete.
else
{
wait(0);
printf("\nI am the parent process, my pid = %d\n\n", getpid());
}
You should check if wait() succeeds and main()'s return type should be int.

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

getting child process ID from the parent using C

I'm trying to write a C program where I have one parent that create two childs.
My task is to retrieve the process ID of the parent of and both childs. For this I've been using getpid().
Now I've been asked to get the child information from the parent. I don't get how I can do this. Like how can I obtain the processing ID for a child from the parent?
I have this at the moment (simplified)
fork1 = fork();
if (fork1 < 0)
fork error
else if (fork1 == 0) {
child 1
use getpid()
use getppid()
} else {
fork2 = fork();
if (fork2 < 0)
fork error
else if (fork2 == 0) {
child 2
use getpid()
use getppid()
} else
parent again
}
After a minute of googling I found this page, where everything you need is written:
System call fork() is used to create processes. It takes no arguments and returns a process ID.
I highlighted the part which is importand for you, so you don't need to do anything to get the process IDs of the children. You have them already in fork1 and fork2!
Here is some code which will print the PIDs from parent and children.
#include <stdio.h>
int main() {
int fork1 = fork();
if (fork1 < 0) {
printf("error\n");
} else if (fork1 == 0) {
printf("I'm child 1\n");
printf("child 1: parent: %i\n", getppid());
printf("child 1: my pid: %i\n", getpid());
} else {
int fork2 = fork();
if (fork2 < 0) {
printf("error\n");
} else if (fork2 == 0) {
printf("I'm child 2\n");
printf("child 2: parent: %i\n", getppid());
printf("child 2: my pid: %i\n", getpid());
} else {
printf("I'm the parent\n");
printf("The PIDs are:\n");
printf("parent: %i\n", getpid());
printf("child 1: %i\n", fork1);
printf("child 2: %i\n", fork2);
}
}
return 0;
}
fork() returns two different values, it returns zero to the child and returns non-zero positive value to the parent, this value is the child process ID, so in your last else, fork1 is the pid of child1 and fork2 is the pid of child2.

Creating new processes

I am creating new processes by forking:
printf("original process = %d\n", getpid());
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
if(fork() == 0){
printf("parent = %d; child = %d\n", getpid(), getppid());
if(fork() == 0){
printf("parent = %d; child = %d\n", getpid(), getppid());
}
}
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
and I want to print out how many processes I have created. My approach as seen above is not the best way of printing how many processes have been created. So my question is: how can we print how many new processes have been created each time we fork without having some kind of loop?
Each successful call to fork creates a new process, and both the parent and the child return from fork(). The child will get 0 as return, the parent the PID of the child.
printf("I am the root %d\n", getpid());
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
if (fork() == 0)
{
printf("I am %d, child of %d\n", getpid(), getppid());
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
}
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
And so on...
The problem in your code is that you are printing the text in some cases without checking the return value of fork(), so these lines will be printed both by the parent and the child. With my code, each process prints just one line, on creation.
As each creates/spawns a child process,
Based on the order in which the fork() is called
Totally 24 child process are created, this is how its done
1st fork(); (has 4 more fork() calls)
2st fork(); (has 3 more fork() calls)
3st fork(); (has 2 more fork() calls)
4st fork(); (has 1 more fork() calls)
So the totall number of child process would be 4! - 1, that is 4x3x2x1 = 24 - 1
23 child process are created

Resources