I'm trying to send a request to a server, and fork it each time beforehand:
int main(void)
{
// request send
fork();
// errx() error handling
return 0;
}
This however only causes 1 fork, then the program crashes. I've been browsing through some docs online and cannot figure out what I'm doing wrong and why it isn't forking each time it attempts to query a server.
Your main problem is execution path. Both parent and child process continue to errx
, which apparently kills the active process, meaning no iterations in the parent or child. You don't check the result of fork
, which is purposely there to help you tell if the function (a) worked, and (b) the current process is the parent or just-forked child.
You're better off setting up the parent process to be a watchdog, and launching the child processes to be guarded. A simple shell example is below, which sequentially launches child processes, waiting for each to terminate.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for (int i=0; i<10; ++i)
{
pid_t pid = fork();
if (pid == 0)
{
// handle child process here
sleep(1);
return EXIT_SUCCESS;
}
if (pid < 0)
{
perror("Failed to launch child process");
exit(EXIT_FAILURE);
}
else
{
printf("child %d started\n", (int)pid);
int res = 0;
pid = wait(&res);
printf("child %d exited, result = %d\n", (int)pid, WEXITSTATUS(res));
}
}
return EXIT_SUCCESS;
}
Example Output
child 72916 started
child 72916 exited, result = 0
child 72917 started
child 72917 exited, result = 0
child 72919 started
child 72919 exited, result = 0
child 72920 started
child 72920 exited, result = 0
child 72921 started
child 72921 exited, result = 0
child 72923 started
child 72923 exited, result = 0
child 72924 started
child 72924 exited, result = 0
child 72925 started
child 72925 exited, result = 0
child 72926 started
child 72926 exited, result = 0
child 72927 started
child 72927 exited, result = 0
Monitoring Batches
For a more complicated version, the following launches child processes in batches of three, then waits for all three to terminate before launching the next batch. This is repeated three times for a total of nine processes total (ten, including the parent watchdog).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for (int i=0; i<3; ++i)
{
// batch launch loop
int n_children = 3;
for (int j=0; j<3; ++j)
{
pid_t pid = fork();
if (pid == 0)
{
// handle child process here
sleep(1);
return EXIT_SUCCESS;
}
else if (pid < 0)
{
perror("Failed to launch child process");
--n_children;
}
else
{
printf("child %d started\n", (int)pid);
}
}
// batch wait loop
for (int j=0; j<n_children; ++j)
{
int res;
pid_t pid = wait(&res);
printf("child %d exited, result = %d\n", (int)pid, WEXITSTATUS(res));
}
}
return EXIT_SUCCESS;
}
Example Output
child 73190 started
child 73191 started
child 73192 started
child 73190 exited, result = 0
child 73191 exited, result = 0
child 73192 exited, result = 0
child 73193 started
child 73194 started
child 73195 started
child 73194 exited, result = 0
child 73193 exited, result = 0
child 73195 exited, result = 0
child 73196 started
child 73197 started
child 73198 started
child 73196 exited, result = 0
child 73197 exited, result = 0
child 73198 exited, result = 0
Hopefully you'll find some of that helpful.