Wait for all child processes in fork chain - c

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

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.

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

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

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.

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.

Resources