fork exec wait loop for a command line entered value - c

I'm trying to exec a file within another file for maximum 5 times and save results. I use a fork-exec-wait in a for loop, this is how it looks like:
for(i = 0; i< Number_of_Processes; i++){
pid = fork();
if(pid == 0)
{
execl(...);
exit(EXIT_Failure);
}
else if(pid > 0)
{
wait(&status);
result = WEXITSTATUS;
}
}
The problem is, it executes the second file for first time correctly and then reprints the first result for 5 times(or whatever the user entered)
I tried so many other ways, like break when it's pid == 0 but it didn't work. i couldn't find a proper example of how to use exec within a loop so I'm stuck for hours, trying moving functions up and down and get nothing.
Whatever i do, i can't see a second execution of the inner file.

Apparently it was a problem of timing, when i add a sleep(1) just before execl in child process, it fixed everything and execed needed processes one by one and printed true results
for(i = 0; i< Number_of_Processes; i++){
pid = fork();
if(pid == 0)
{
sleep(1);
execl(...);
exit(EXIT_Failure);
}
else if(pid > 0)
{
wait(&status);
result = WEXITSTATUS;
}
}

Related

how to run multiple children with different tasks?

My program has to create multiple children, i take the number of children from terminal. Then, I need to group them and every group has different tasks.
I created the children but the problem is that I can't give them separated tasks, I can't distinguish children. Only thing I can do is, every children works on the same part(like printing pids).
How can I separate them and give them specific tasks?
For example, first 4 children should call a function, other 3 should print something and other 3 should write to a file etc.
pid_t pid[10];
pid[0] = fork();
if(pid[0] > 0)
{
for(int i = 0; i < 9; i++)
{
if(pid[i] > 0)
{
pid[i + 1] = fork();
}
}
}
for(int i = 0; i < 10; i++)
{
if(pid[i] == 0)
{
printf("child %d, parent %d\n", getpid(), getppid());
exit(1);
}
}
I think you should take a look at how the fork() function works. Here is the man page, here a useful answer and here a useful tutorial.
When you use fork() in your code, know that the child process continue from where the parent was. So when you call fork() in the first for loop, all the child processes continue the loop that the parent has begun. I don't think this is the behavior you expect.
Anyway, here's a possible solution for your problem. In this way your processes do some stuff divided in small groups. Note the exit(0) function at the end of the work. It is important to be sure that every process does only its work and not also its parent's work:
pid_t pid[10];
for (int i = 0; i < 9; i++)
{
pid[i] = fork();
//First group
if (pid[i] == 0 && i < 4){
//Insert here the code for the first group or call a fuction
exit(0);
}
//Second group
if (pid[i] == 0 && i >=4 && i < 8){
//Insert here the code for the second group or call a fuction
exit(0);
}
//Third group
if (pid[i] == 0 && i >=8){
//Insert here the code for the third group or call a fuction
exit(0);
}
if (pid[i] < 0){
perror("Something wrong with the fork");
exit(1);
}
}
int flag = 0;
flag |= (fork() == 0) << 0;
flag |= (fork() == 0) << 1;
flag |= (fork() == 0) << 2;
printf("this process works on problem %d\n", flag);

execvp in C not going through ar

I'm trying to use exec to execute a list of commands given as arguments.
Example input when In run the program would be ./assn2 ls date.
When I do this only the first command is executed.
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
int args = argc-1;
pid_t childpid = fork();
// error
if (childpid < 0)
{
perror("fork() error");
exit(-1);
}
// parent process
if (childpid != 0)
{
printf("Parent Process started, now waiting for ID: %d\n", childpid);
wait(NULL);
printf("Parent Process resumeed. Child exit code 0. Now terminating\n");
exit(0);
}
// child process
if (args > 0)
{
printf("Child process has begun. %d argument/s provided\n", args);
int i;
for (i = 1; i <= argc; i++)
{
execlp(argv[i], argv[i], NULL);
}
execvp(argv[1], argv);
}
else
{
printf("No arguments provided, terminating child\n");
}
return 0;
}
Once the first child process execs (and succeeds), the for loop no longer continues because the an execlp would just replace the current process image with the command being exec'ed.
What you want to do is to loop over the command line arguments in the parent process and exec once for each of the command. Something like is probably what you're after:
for(int i = 1; i < argc; i++) {
pid_t pid = fork();
if (pid == 0) {
execlp(argv[i] ,argv[i], (char*)0);
perror("exec");
} else if (pid > 0) {
wait(NULL);
} else {
perror("fork");
exit(1);
}
}
What are you trying to achieve with the sequential calls to execlp() and execvp()? These functions are not meant to return. I think you should read the ref:
The exec() family of functions replaces the current process image with a new process image. [..] The exec() functions only return if an error has occurred.
As a result you cannot execute them one after another in the same process.
Read about fork():
fork() creates a new process by duplicating the calling process.
Moreover, here:
for(i = 1; i <= argc; i++)
you go out of bounds, since argv starts indexing from 0, and ends at argc - 1.
Chnage it to:
for(i = 1; i < argc; i++)

multiple processes using fork()

I'm using this to set up a process in my main:
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
How would I go about setting more processes, say for example x4 of them?
If you're in the parent process, call fork() again to get another child. If you put it in a loop then you're golden.
for (int i = 0; i < 4; ++i) {
pids[i] = fork();
if (pids[i] == 0) {
ChildProcess();
break;
}
}
Make sure the child does not call fork(). Only the parent.
There is some ways to do this.
For example:
1. just repeate your fork() for 4 times.
2. use a loop to call fork() for 4 times.
3. wrapps those into a functions

Spawn multiple children processes

So I want to spawn a number of children processes equal to a value inputted from the command line. I have all the values and everything reading in just fine, I just need to figure out how to spawn these children, and have them all call the same program.
Here is what I have so far:
for(int i = 0; i < processes; i++)
{
pid = fork();
printf("%d\n", pid);
}
if(pid < 0)
{
perror("fork");
exit(-1);
}
else if(pid == 0)
{
/*for(int j = 0; j <= 5; j++)
{
execl("~/cs370/PA2/gambler.c","run", NULL);
Gamble(percent);
}*/
}
So to be clear again. I want to spawn "processes" amount of children, that all call "gambler.c". But ONLY 5 can be running at a time. It should wait(), and then process the rest of the children 5 at a time.
Sample input:
run -p 60 10
Where -p is a percentage to be fed to gambler.c which just returns success or failure based on a random number generator. 60 is the percentage. 10 is the number of processes.
Any help is much appreciated thanks!
Have you looked into the exec family? Exec will spawn processes. You can then use wait to monitor the processes. fork will give you the PID and you can then have a second thread loop over each pid calling wait and keeping track of each active process.
wait man page
exec man page
pid_t pid = fork()
if (pID == 0)
{
//child
//immediatly call whichever exec you need. Do not do anything else.
//do not log a message or print a string. Any calls to c++ standard strings
//will risk deadlocking you.
}
else if (pid < 0)
{
//error
}
else
{
//parent. store pid for monitoring
}

Preventing grand children from forking in C

I have the following code in which I'm trying to create sub processes by forking. I want that exactly 3 sub processes are made. However, when I run the code I seem to be getting more, probably because of the children processes forking grandchildren. What am I missing here, how can I prevent this.
Code:
for(j = 0; j < 3 ; j++){
if((pid = fork()) == 0){ // child process
dosomething();
exit(0); // terminate child process
}
else if((pid = fork()) > 0){
printf("I'm in parent of the client spawn loop\n");
// exit(0);
}
}
Output:
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
Don't do the second fork call as it will create a new child. The first is enough:
for (j = 0; j < 3; ++j)
{
pid_t pid = fork();
if (pid == 0)
{
printf("In child (j = %d)\n", j);
exit(0);
}
else if (pid > 0)
{
printf("In parent (j = %d)\n", j);
}
}
Will print "In child" three times, with j equal to 0, 1 and 2. The same for the parent printing.
In your real code you should check for errors though.
Don't call fork() more than once in the loop.
The parent shouldn't call fork() again, that will create yet another child and introduce another child-parent split point.
You should have, in the loop:
const int pid = fork();
if(pid == 0)
{
doSomething();
exit();
}

Resources