Forking in a loop does not work as thought - c

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.

Related

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.

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

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.

fork: child process doesn't stay in an infinite loop

#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
printf("pid : %d\n", getpid());
if( pid == 0)
{
printf("child: pid : %d \n", getpid());
while(1);
}
else
{
printf("parent: pid : %d \n", getpid());
//while(1);
}
}
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked and when enter key is pressed program is exited, but in case of parent if we put while(1), parent remains blocked until we give ctrl+c. Please clarify this behaviour of child.
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked
The child process doesn't exit actually; it just becomes an orphan process because its parent exits. The orphaned chuld process will be adopted by the init process of your system. You can see it via ps command.
But if you put the while(1); in the parent process it remains blocked.
Basically whichever process has while(1); infinite loop, it's still running. When parent exits you get the prompt back and the child becomes orphan. But the child process is still running.
In general, you need to wait(2) for the child process in the parent process to reap child processes.

Is there a good way to alter execution order of child processes created with fork()?

I am looking for creating child processes for which I can control their order of processing.
Simple example:
Parent creates 2 children with fork
Children
First child prints "Message 2"
Second child prints "Message 1"
When this is finished parent prints "End"
Because of the fact that we can't know for sure which process will be executed first, there are high chances that the final result would be:
Message 2
Message 1
End
I am trying to make sure that the second child executes the print before the first child and that the parent executes its print after all the children.
For the parent it's quite easy with the wait()/waitpid() functions. However it seems harder with the children.
Here is an implementation of my ideas to achieve the objective:
(note: I'm still quite new to the creation of child processes and I may have misunderstood things in this implementation)
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
static int init = 0;
void setInitFinished(int sig)
{
if (sig == SIGUSR1)
init = 1;
}
int main()
{
signal(SIGUSR1, setInitFinished);
pid_t pid1, pid2;
int status1, status2;
// CHILD 1
if (!(pid1 = fork()))
{
while (!init); // Waiting all children to be initiated
// Once all children created, we wait for child 2 to print its message
int pidOfChild2 = getpid()+1; // I checked, the PID is correct
waitpid(pidOfChild2, &status1, 0);
printf("MESSAGE 2\n");
exit(0);
}
// CHILD 2
if (!(pid2 = fork()))
{
while (!init); // Waiting all children to be initiated
// No need to wait since it's the first message to be printed
printf("MESSAGE 1\n");
exit(0);
}
// PARENT
// All children have been created, tell it to all the children
kill(pid2,SIGUSR1);
kill(pid1,SIGUSR1);
// When every child has finished its work, continue parent process
waitpid(pid1, &status1, 0);
waitpid(pid2, &status2, 0);
printf("Parent end\n");
return 0;
}
In the child 1 I am trying to wait for the Child 2 with waitpid(pidOfChild2, ...); but it doesn't seem to work.
I'm still discovering the fork functionalities so I'm pretty sure to misunderstand a lot of things here.
NB: I want to avoid using sleep(), it could work but it's not pretty
You need to use actual inter-process communication to achieve this.
You seem to think that the waitpid() function has something to do with waiting for a process to print output, but that's not at all what it does.
Create a semaphore in the parent, pass it to both children, and have one child wait on the semaphore before printing and the other one messaging the semaphore after it's done printing.

Why the output is printing twice?

May be it look childish for most of you but I am unable to understand this small piece of code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char** argv) {
int i, pid;
pid = fork();
printf("Forking the pid: %d\n",pid);
for(i =0; i<5; i++)
printf("%d %d\n", i,getpid());
if(pid)
wait(NULL);
return (0);
}
Out put of this program is
Forking the pid: 2223
0 2221
1 2221
2 2221
3 2221
4 2221
Forking the pid: 0
0 2223
1 2223
2 2223
3 2223
4 2223
Press [Enter] to close the terminal ...
In the for loop the printf command is used once. Why "Forking the pid" and after that the pid's are printed twice. How this is working? Can anybody explain me this? Thanks in advance.
Can anybody explain me why we have to use wait here? What I understood from the man pages is wait retuns the control to parent process? Is what I understood is correct?Is it necessary to use wait after forking a process?
Operating system : ubuntu, compiler : gcc, IDE : netbeans
But that' exactly what fork does. You forked the process and everything after the fork is done twice because now you have two processes executing the same printing code. You are basically asking why fork forks. fork forks because is is supposed to fork. That's what it's for.
After fork the parent and the child processes are generally executed in parallel, meaning that the nice sequential output you see in your example is not guaranteed. You might have easily ended up with line-interleaved output from two processes.
wait function in your case is executed from the parent process only. It makes it wait until the child process terminates, and only after that the parent process proceeds to terminate as well. Calling wait in this particular example is not really critical, since the program does nothing after that, it just terminates. But, for example, if you wanted to receive some feedback from the child process into the parent process and do some additional work on that feedback in the parent process, you'd have to use wait to wait for the child process to complete its execution.
The fork() call makes a new process. The rest of the code is then executed from each of the 2 processes. (Man page)
You're printing in both processes. Put your printing loop in an else clause of the if (pid):
pid = fork();
if(pid)
{
printf("Child pid: %d\n",pid);
wait(NULL);
}
else
{
for(i =0; i<5; i++)
printf("%d %d\n", i,getpid());
}
You see, fork returns twice, once in the parent process and once in the child process. It returns 0 in the child and the pid of the created process in the parent.
Because both the parent and child process are outputting their results.
See here: http://en.wikipedia.org/wiki/Fork_(operating_system)#Example_in_C for a good example.
fork creates a new process, and returns in both the old process (the parent) and in the new process (the child).
You can tell which one you are in by looking at the return value from fork. In the parent process it returns the PID of the child process. In the child process it return 0.

Resources