Fork and waiting for the childs outside the pid check - c

I want to make two parallel working forks and in the end wait for them to finish.
for (int i = 0; i < 2; i++) {
pid_t pid = fork();
if(pid < 0) {
fprintf(stderr,"Cannot fork!");
exit(EXIT_FAILURE);
}
else if(pid == 0) {
switch(i)
{
case 0:
//first child
exit(EXIT_SUCCESS);
break;
case 1:
//second child
exit(EXIT_SUCCESS);
break;
}
break;
}
else {
//parent
}
}
The problem is that the main program terminates before the child ones. If I add wait(0) to the else parent part it waits to every process so they don't work at the same time but one by one.
I assumed that I can simply put the wait() or waitpid() after the loop but that's not working either. I thought that after the fork the parent continues normally so why doesn't it wait when the wait() is outside the loop and if-else structure?
Sorry for bothering and thanks in advance.

If you add wait(NULL) inside the else parent part, the parent-process will indeed wait for the first child-process to return before it creates the second.
If you add wait(NULL) after the loop, the parent process will wait only once, for the first child-process that will return.
If you want all children-processes to run at the same time, you need a second loop, where the parent-process will use wait() as many times as needed to collect the exit status of every child-process.
In your case, there are 2 children-processes, thus 2 wait() system calls are enough. The loop to add would be like this (I also added a printf so that you can observe it on your stdout):
for (i = 0; i < 2; i++) {
wait(NULL);
printf("My child No %d died.\n", i);
}

Related

Fork() with multiple children and with waiting for all of them to finish

I want to create a program in C, where I use fork() to create multiple children, then wait for all of them to finish and do parent code (only once).
I tried using for loop and two forks but I there is a problem: either parent code isn't running at the end or children are not running parallel.
//Number of processes I want to create
int processes = 6;
pid_t *main_fork = fork();
if(main_fork ==0){
for(int i=0;i<processes;i++){
pid_t *child_fork = fork();
if(child_fork ==0){
// child code
exit(0);
}
else if(child_fork >0){
//And here is the problem, with the wait: children don't
//run parallel and if I delete it, the main parent code doesn't run
wait(NULL);
}else{
// Child fork failed
printf("fork() failed!\n");
return 1;
}
}
}else if(main_fork >0){
wait(NULL);
//Main parent code - here I want to do something only once after all
//children are done
}else{
// Main fork failed
printf("fork() failed!\n");
return 1;
}
If somebody could could fix my code, or write a better solution to this problem I would be so grateful!
If you want all the children to run in parallel, you have to do the wait after all the children has been started. Otherwise you start a child, wait for it to finish, start a new one, wait for that to finish, start a third one, wait for the third one to finish, and so on...
So what you typically want to do is to start all the children and put all the pid_t in an array, and when you are finished you may call wait() for each pid_t
This is the simple, and good enough solution for your case.
Here is a sample code that you can fit to your problem:
pid_t children[processes];
for(int i=0; i<processes; i++)
{
pid_t child = fork();
if(child == 0)
{
// child code
....
// We call _exit() rather than exit() since we don't want to clean up
// data structures inherited from parent
_exit(0);
}
else if (child == -1)
{
// Child fork failed
fprintf(stderr, "myprog: fork failed, %s", strerror(errno));
// Do real cleanup on failure is to complicated for this example, so we
// just exit
exit(EXIT_FAILURE);
}
children[i] = child;
}
// Do something if you want to do something before you expect the children to exit
....
for(int i=0; i<processes; i++)
{
pid_t child = children[i];
int status;
waitpid(child, &status, );
// Do something with status
}
Naturally this is not a complete example that fits any situation. Sometimes you have to tell the children when they should exit. Other times the children are not started/stopped in one go, and you have to play with asynchronous events, and so on...

C - meaning of wait(NULL) when executing fork() in parallel

In the code below, do the forks actually run in parallel or one after another?
What is the meaning of wait(NULL) ?
(The program creates an n number of child processes, n is supplied via command line)
int main ( int argc, char *argv[] ) {
int i, pid;
for(i = 0; i < atoi(argv[1]); i++) {
pid = fork();
if(pid < 0) {
printf("Error occured");
exit(1);
} else if (pid == 0) {
printf("Child (%d): %d\n", i + 1, getpid());
exit(0);
} else {
wait(NULL);
}
}
}
They do run in parallel, up until the point that one of them waits.
wait(NULL) or more accurately wait(0) means wait until a state change in the child process. To find out about Unix / Linux C api calls, type man <function Name> on the command line. You'll need to get used to reading those pages, so better start now.
In your case
man wait
would have given you what you needed.
Since you've only fork(...)ed once, you have only one child. The parent waits until it changes state, and since the child's state during the fork is the same as the parent's state prior to the fork (that of running), the likely outcome is that the parent waits until the child dies. Then the parent will continue executing, but since it doesn't have much to do after the wait(...) call, it will quickly exit too.

Spawning C child process for different jobs?

So I am trying do a application which fork()s 2 children.
first does a for(i=1; i<=50000; i++) loop
the second a for(i=50000; i<=100000; i++) loop
the parent does for(asciic=65; asciic<=90; asciic++)-> loop for printing A to Z letters
I need all three to do they're work simultaneous not one after another.
I've looked over the internet and I couldn't found a proper way, all I could find are loops which create the children processes but they do almost the same thing and most are created one after another.
Any help is appreciated.
To be more understood, this is what I've done before posting:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
pid_t child_pid,child_pid1;
int i=0;
int stare;
int asciic;
child_pid=fork();
child_pid1=fork();
if (child_pid==0) {
//printf("Father PID: %d -> Child 1: %d\n",getppid(),getpid());
for(i=1; i<=50000; i++){
printf("%d-%d\n",getpid(),i);
}
exit(0);
} else if (child_pid1==0) {
//printf("Father PID: %d -> Child 2: %d\n",getppid(),getpid());
for(i=50000; i<=100000; i++) {
printf("%d-%d\n",getpid(),i);
}
exit(0);
} else {
//printf("PID-ul procesului parinte: %d\n", getpid());
pid_t rez=waitpid(child_pid,&stare,WNOHANG);
pid_t rez1=waitpid(child_pid1,&stare,WNOHANG);
while(rez==0 || rez1==0){
for(asciic=65; asciic<=90; asciic++){
printf("%d- %c\n",getpid(),asciic);
}
rez=waitpid(child_pid,&stare,WNOHANG);
rez1=waitpid(child_pid1,&stare,WNOHANG);
}
}
return 0;
}
If I comment out the loops I can see that the children have different PIDs, 1 child has the right parent PID and other it has other parent PID.
Your 2 lines with forks:
child_pid=fork();
child_pid1=fork();
do not create 2 children, but three: the parent creates a first child in the first fork(). From that moment there are 2 processes: parent and child. And each of them executes the second fork(). You will have in total 1 parent, 2 children and 1 grandchild.
In order to have just 1 parent and 2 children, you will have to:
pid1 = fork();
if (pid1 < 0) {
/* Error in fork() */
} else if (pid1 == 0) {
/* first child */
exit(0);
}
pid2 = fork();
if (pid2 < 0) {
/* Error in fork() */
} else if (pid2 == 0) {
/* second child */
exit(0);
}
/* parent */
Moreover, even when your code is correct, you cannot "see" if the processes are running concurrently or not just looking at their outputs. In fact, even if there are multiple processes executing "at the same time", you may see that one of the processes finishes before another one starts. That is because typically the kernel does time multiplexing to offer each child some CPU time. You can see concurrency if the processes take longer to complete, for example adding some sleep().
The problem is here:
child_pid=fork();
child_pid1=fork(); // This line will be executed by both parent and first child!!!
You need to move the second fork into the parent part of the first if, and then have a separate if for the second child.
fork() returns the pid_t of the child to the caller (parent), or -1 if it failed. In the child, 0 is returned. You can simply test
if (fork())
{
//do one thing
}
else
{
//do something else
}

making children processes wait for another for loop

i've been making google searches about my question for 2 days but im done with it. I have very basic information about process management, fork etc. I've been told to create some children processes of a same parent process and send them seeds by using pipes so they can produce some random numbers, all for their own. But I'm stuck at creating children processes.
for (i = 0; i < NUM_PLAYERS; i++) {
/* TODO: spawn the processes that simulate the players */
switch(pid = fork()){
case -1: // ERROR
exit(EXIT_FAILURE);
case 0: // CHILD PROCESS
printf("My parent id is %d \n", getppid());
exit(EXIT_SUCCESS);
default: // PARENT PROCESS
wait(NULL);
}
}
When I go with this code, parent creates NUM_PLAYERS children but I can't seem to use them in another for loop since they had terminated at the end of the case 0. When I just remove exit(EXIT_SUCCESS); line, so many processes are created and they have all different parents. So my question is, how to properly create children processes and use them later?
If you remove exit(EXIT_SUCCESS) your child will continue executing where it was forked, IE it will go back to the close brace of the for() loop, and generate new children itself. What do you want the child to do? You should make it do that, and then do exit(EXIT_SUCCESS) and not let it return to to the for() loop.
Note also that wait() will only wait for one process to quit.
void do_something()
{
//create random numbers or whatnot
}
//...........
case 0: // CHILD PROCESS
printf("My parent id is %d \n", getppid());
do_something();
exit(EXIT_SUCCESS);
You'll need the parent to wait on the children in a later loop. The way you have it will block until a single child returns. You want to create multiple children before then waiting on them.
Note that you still have to add the pipe logic so parent/child can communicate.
EDIT
This is the broad outline of what you need to do:
for (i = 0; i < NUM_PLAYERS; i++) {
/* TODO: spawn the processes that simulate the players */
switch(pid = fork()){
case -1: // ERROR
exit(EXIT_FAILURE);
case 0: // CHILD PROCESS
printf("My parent id is %d \n", getppid());
exit(EXIT_SUCCESS);
}
}
// only the parent will ever execute below here
for (i = 0; i < NUM_PLAYERS; i++)
{
while ( /* read each child's pipe*/)
{
//do something with data
}
}
for (i = 0; i < NUM_PLAYERS; i++)
wait(NULL);
return(0);

Theory,Processes fork()

Goodmorning, i would like to ask 2 things..
1) what returns a fork() did on a child which has already a pid==0 ? if i continue to fork on every son, each of them will have 0 as pid ?? or not ?
2) this is my file Buffer.c and it runs on a single process.
At the beginning it forks() out some Producers who produce() and some Consumers who consume() ,but I am afraid that every producers enters in the next for cicle and it starts to produce himself other consumers!! because it write pid=-1 so...
I want that this piece of code produce only P producers and C consumers, but i need to know why every producer do not create other consumers!
Can you help me,maybe giving me a scheme of how many processes i will create with this code?
Maybe doing a scheme as this:
Father:
8 producers
-
-
-
...
each of them produces: 5 consumers
etc etc......
int main(int argc, char **argv) {
/....
pid_t pid;
pid_t cons_pid[C];
/* fork producers */
pid = -1;
for(i=0; i<P && pid!=0; i++)
pid=fork();
switch(pid) {
case -1:
...
case 0:
/* GENERIC PRODUCER i */
...
/* PRODUCE() */
printf("Producer %d exits\n",i);
...
return 0;
}
/* fork consumers */
pid = -1;
for (j=0; j<C && pid!=0; j++)
pid = cons_pid[j] = fork();
switch(pid) {
case -1:
....error
case 0:
/* GENERIC CONSUMER j */
CONSUME()....
}
return 0;
}
what returns a fork() did on a child which has already a pid==0
0 is not a valid PID, hence by definition there can't be an process with PID=0 and thus PID=0 is a perfectly well defined return for indicating child status.
if i continue to fork on every son, each of them will have 0 as pid
No process ever has PID=0. All PIDs are greater than zero! A zero is just the return value received by the newly forked process to indicate that it's the child. The actual PID a child process got is queried using the getpid function from the child process. However the parent process can't perform such a query, since in the time between fork and a assumed query function call, the child may already have terminated (race condition). So you want fork to return the PID to the parent directly.
BTW: The terminology is parent and child not father and son (processes are things not people, despite what the TRON movies depict).
Regarding your code snippet: A switch statement is the wrong choice here. You want to use an if statement.
fork() splits up the current process into a father and a child. The child will have a new PID, the father retains the old PID. In both processes fork() returns after the splitting. In the father the return value will be the PID of the child (to make it known), and in the child the return value will be 0.
1) The lowest possible process ID is 1, this is the ID of the init process from which all other processes are forked. Therefore, it is not possible for a child or for your parent process to "already have ID 0". Your child's process ID is necessarily greater than 1. Thus, the problem that you are afraid of cannot happen.
2) The confusion that you state is the reason why fork (which returns twice, once for the parent and once for the newly created child!) has a somewhat "weird" return value which can have so many different values:
it can be -1, then something went wrong, and no child was created.
it can be a positive value, then you are in the parent process, and the value is the child's process ID. It's as if you called any other "normal" function that just returned normally.
it can be 0, then your code knows it is now running in the child process.
You must examine the return value (if()) so you know what process you are in. Then no such thing as you decribe can happen (or, should happen, this presumes your code does not have any bugs).
EDIT:
The code can be rewritten slightly so it gets rid of the && pid!=0 inside the loop and thus looks a bit less scary overall:
int main()
{
int pid, i;
pid_t cons_pid[C];
for(int i=0; i<P; ++i)
{
pid=fork();
if(pid == -1) exit(1); /* fork error */
if(pid == 0) { producer(); return 0; }
}
for(i=0; i<C; ++i)
{
pid = fork();
if(pid == -1) /* fork error */
{ /* should do a kill_producers(); here */ exit(2); }
else if(pid == 0) /* consumer */
{ consumer(); return 0; }
else /* master process, remember all consumer pids */
{ cons_pid[j] = pid; }
}
/* ... */
return 0;
}

Resources