I need to fork many short life processes. (But I don’t want to wait until it is finished. Just let it run.). After some time, I receive error when executing fork (errno == 11). It looks like the forked processes still exists (at least they are visible in htop).
For instance, please consider the following example. I want to fork a process and then exit it shortly after.
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
void RunProc(){
pid_t pid = fork();
if(pid == 0)
{
puts("fork with success");
//no needed to reproduce issue. Used in my code to run some commands.
//execvp()
exit(0);
}
else if (pid == -1) {
printf("Could not start processn");
printf("Errno: %dn", errno);
}
else {
}
}
int main()
{
while(true){
RunProc();
}
int res = 0;
int i = 5;
res = scanf("%d", &i);
res = printf("End of program %dn", i);
return res;
}
At the beginning it runs correctly. After several minutes I receive only errors:
Could not start process
Errno: 11
And I’m not able to start new fork anymore.
I’m running it on Ubuntu 22.04
2
Answers
You need to call one of the
wait
functions in the parent process, to reap the child-process when it exits.You could use e.g.
waitpid
with theWNOHANG
flag to poll for child-process exit. Or use theSIGCHLD
signal to learn when a child process have exited.There’s only a limited number of process-slots available in your system, if you don’t reap the child processes, they will fill up all the slots and lead to the error you get.
As the
fork
manual page say about theEAGAIN
error:When process terminates, its PID and exit status still remains as a record in process table. This is so called zombie process. You can remove it by reading its status with one of
wait()
functions family, as described in sibling answer.If you don’t need to care about status of child processes, you can allow
init
to read their status and cleanup the table. When parent process terminates,init
(process with PID 1) becomes parent of all its children processes by default. Thus you can use double fork to makeinit
to be a parent of your processes: