Capturing exit code of n child processes - c

I am trying to fork() 10 child processes in one loop and then in another loop wait() for them to terminate and print their PID along with their exit status code. It cannot be done any other way or using any other function. Two loops/waves and the function wait();
This is what I have tried:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t wait_p, p[10], p_child;
int status;
for (int i = 0; i < 10; i++)
{
p[i] = fork();
}
for (int i = 0; i < 10; i++)
{
switch (p[i])
{
case 0:
p_child = getpid();
exit(p_child % 10);
break;
case -1:
puts("ERROR");
break;
default:
wait_p = wait(&status);
printf("Child with PID: %d", wait_p);
if (WIFEXITED(status))
printf(" terminated with STATUS: %d\n", WEXITSTATUS(status));
break;
}
}
return (EXIT_FAILURE);
}
This code will execute an endless count of child processes. It must print only the first original(issued by THE one parent) 10. What am I doing wrong?

You have to handle the child processes directly in your first loop:
for (int i = 0; i < 10; i++)
{
p[i] = fork();
if (p[i] == 0) {
p_child = getpid();
exit(p_child % 10);
} else if (p[i] == -1) {
perror("fork");
}
}
and then wait for them in the second loop
for (int i = 0; i < 10; i++)
{
wait_p = wait(&status);
printf("Child with PID: %d", wait_p);
if (WIFEXITED(status))
printf(" terminated with STATUS: %d\n", WEXITSTATUS(status));
}
You cannot handle the case, that fork() returns in the child process (yielding 0 as return value), in your second loop, otherwise each child process in the first loop keeps forking more child processes.

Related

fork() 4 children in a loop

The goal is to try and fork 4 children in a loop, but I'm not sure how to properly do that. This is what I have so far. I tried to draw it out and I think I'm not waiting to reap the child properly. And I create like 2 children every iteration. So, 8 children in total.
void main() {
int i = 0;
pid_t pid;
int status;
for(i = 0; i < 4; i++) {
pid = fork();
if(pid == 0) {
/* Child Process */
fork();
exit(0);
} else {
/* Parent Process */
wait(&status);
printf("At i = %d, process %d is terminated.\n", i, pid);
}
}
}
Creating four children processes from the same parent process can be achieved by forking once on each iteration of the for loop:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
for (int i = 0; i < 4; i++) {
pid_t pid = fork();
if (pid == 0)
exit(0); // child process
// parent process
wait(NULL);
printf("At i = %d, process %d is terminated.\n", i, pid);
}
}
However, you probably want the parent process to wait for the children after it has created all of the four children, because you usually want the children to do something before exiting and concurrently with the other children:
int main() {
// create the four children processes
for (int i = 0; i < 4; i++) {
pid_t pid = fork();
if (pid == 0) {
// child process
// ... do some stuff ...
exit(0);
}
}
// wait for the four children processes to finish
for (int i = 0; i < 4; i++) {
pid_t pid = wait(NULL);
printf("Process %d is terminated.\n", pid);
}
}

Why the child process is not executed?

I have the following piece of code:
int main() {
int n = 1;
if(fork() == 0) {
printf("child");
n = n + 1;
exit(0);
}
n = n + 2;
printf("%d: %d\n", getpid(), n);
wait(0);
return 0;
}
The problem is that I don't understand why the child process is not executing.
The child process is executing only if i set sleep(1) in the parent process
Thanks in advance.
It is getting executed and it should be outputting the text. No newlines should be necessary:
https://ideone.com/a1tznH
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int n = 1;
if(fork() == 0) {
printf("child");
n = n + 1;
exit(0);
}
n = n + 2;
printf("%ld: %d\n", (long)getpid(), n); //this is how you should print pids
wait(0);
return 0;
}
Example output:
child23891: 3
Perhaps you didn't notice the child text was at the beginning of your next prompt:
18188: 3
child[21:17] pskocik#laptop: $
The child is executed but two processes are trying to write on the same FD - STDOUT (File Descriptor).
If you want to see the result, put "\n" in printf of the child.
int main() {
int n = 1;
if(fork() == 0)
{
printf("child\n");
n = n + 1;
exit(0);
}
n = n + 2;
printf("%d: %d\n", getpid(), n);
wait(0);
return 0;
}
Try
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("fail to fork");
}
else if (pid == 0)
{
printf("running child");
exit(0);
}
else
{
print("running parent");
wait(0);
print("child done");
}
return 0;
This is the basic structure of a program I wrote recently which works. Not totally sure why yours didn't work though.

How to run child processes simultaneously? in c

So here is my code that will take an int as an command line argument then fork N child processes (That run simultaneously). And then when each child ends, the parent will echo the child that child exit status.
But right now I can only do child by child but not simultaneously. How can I do it?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
int main ( int argc, char *argv[] )
{
int i, pid, ran;
for(i = 0; i < atoi(argv[1]); i++) {
pid = fork();
srand(time(NULL));
ran = (rand() % 10) + 1 ;
if (pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
printf("Child (%d): %d\n", i + 1, getpid());
printf("Sleep for = %d\n", ran);
sleep(ran);
exit(ran);
} else {
int status = 0;
pid_t childpid = wait(&status);
printf("Parent knows child %d is finished. \n", (int)childpid);
}
}
}
You're calling wait() inside of the loop where you're spawning the children, so it won't continue the loop to start the next child until the current one is done.
You need to call wait() outside of the loop in a separate loop:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
int main ( int argc, char *argv[] )
{
int i, pid, ran;
for(i = 0; i < atoi(argv[1]); i++) {
pid = fork();
srand(time(NULL));
ran = (rand() % 10) + 1 ;
if (pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
printf("Child (%d): %d\n", i + 1, getpid());
printf("Sleep for = %d\n", ran);
sleep(ran);
exit(ran);
}
}
for(i = 0; i < atoi(argv[1]); i++) {
int status = 0;
pid_t childpid = wait(&status);
printf("Parent knows child %d is finished. \n", (int)childpid);
}
}

Controlling multiple children, handling sigchld

Let's say i have a main C program that has to wait for sigchld of two children, and that these two sons have to do two separate task, for example one should write "1", and the other
one should write "2" ,wait 2 seconds and then terminate, now how should I write the code so that the father write his children's pid only after the two sons ends with sigchld? It's obvious that i'm missing some theory, if you look at my code you will understand what my issue is.
After that i'll have to force the execution of the second son before the first son, suggestion?
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int pids[2], cpid, i, status;
char buff[200];
for(i=0; i < 2; i++)
{
if ((pids[i] = fork()) < 0)
perror("errno");
else
{
//child
if (pids[i] == 0)
{
if(i == 0)
write(1,"1\n", 2);
else
{
sleep(2);
write(1,"2\n", 2);
}
return 0;
}
}
}
for(i = 0; i < 2; i++)
{
cpid = waitpid(pids[i], &status, 0);
if (WTERMSIG(status))
printf("status:%d , pid terminated:\n", status,cpid);
else
printf("error: not exited with a signal\n");
}
return 0;
}
If the last for loop is changed as:
for(i = 0; i < 2; i++)
{
cpid = waitpid(pids[i], &status, 0);
if (WIFEXITED(status))
printf("status:%d , pid %d terminated normally :\n", status,cpid);
else if (WTERMSIG(status))
printf("status:%d , pid %d terminated by signal:\n", status,cpid);
else
printf("error: not exited with a signal\n");
}
Then the thing works better, as there is no signal to terminate the childs.

fork()ing - Idle Children

So I need to iterate fork() several times, creating child processes. The child processes are supposed to "do little or not processing" for example;
while(1)
sleep(1)
The parent is then supposed to gather the PID's of the children and kill them (harsh, I know!).
However they way I'm doing it at the minute executes the code in the "parent" block several times, but I only need it to execute once.
Here is an example; you need to store the pids in a table (here p[]).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#define NSUB 10
int main ()
{
int i, n = NSUB, p[NSUB], q;
for (i = 0; i < n; i++) {
printf ("Creating subprocess %d ...\n", i);
p[i] = fork();
if (p[i] < 0) { perror ("fork"); exit (1); }
if (p[i] == 0) { /* subprocess */
printf ("Subprocess %d : PID %d\n", i, (int) getpid());
while (1) pause ();
exit (0);
}
}
sleep(2);
for (i = 0; i < n; i++) {
printf ("Killing subprocess %d ...\n", i);
if (kill (p[i], SIGTERM) < 0) perror ("kill");
}
for (i = 0; i < n; i++) {
printf ("waiting for a subprocess ...\n");
q = wait (NULL);
printf ("Subprocess terminated: PID %d\n", q);
}
exit (0);
}

Resources