Reputation: 11
I am trying to make a program that checks a list of steam servers using fork. I saw that if i put 100.000 lines servers often the program goes in a wired loop and checks the same servers over and over and over again. After a debug i see that even a simple program that prints the server ip goes unexpected.
Program:
#include <iostream>
#include <sys/wait.h>
#include <stdio.h>
#include <cstring>
#include <unistd.h>
#include <string>
#include <ctype.h>
#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <regex>
#include <vector>
int main(int argc, char **argv)
{
puts("Beginning program");
int max_forks = 500;
int num_forks = 0;
FILE *fpxxx = fopen("servers", "r");
if(fpxxx == NULL) {
perror("Unable to open file!");
exit(0);
}
char chunk[128];
while(fgets(chunk, sizeof(chunk), fpxxx) != NULL)
{
// puts(chunk); // same result if put the line here
if(!(fork()))
{
// sleep(3);
puts(chunk);
exit(0);
}
else
{
num_forks++;
if (num_forks >= max_forks)
{
wait(NULL);
num_forks--;
}
}
}
fclose(fpxxx);
sleep(10);
}
Output :
Beginning forking
94.xxx.xxx.209
Beginning forking
184.xxx.xxx.117
Beginning forking
108.xxx.xxx.86
Beginning forking
178.xxx.xxx.140
Beginning forking
113.xxx.xxx.132
Beginning forking
45.xxx.xxx.16
... (many lines, thus servers.txt has 100.000+ ips)
# after a while i see
Beginning forking
178.xxx.xxx.140
# again and again and again
# sometimes i even see
Beginning forking
37.247.104.933.17.199.143
Expected output :
94.xxx.xxx.209
184.xxx.xxx.117
108.xxx.xxx.86
178.xxx.xxx.140
113.xxx.xxx.132
45.xxx.xxx.16
Do i forget something? Seems like the heap is corrupted. And why i see Beginning forking
as if the program runs again from the begining? I know that forking is making another process but I though that fork()
forks the program from the point where fork()
is.
Thank you.
EDIT : solution is getline() is repeatedly reading the file, when fork() is used
Upvotes: 0
Views: 204
Reputation: 12635
You have several problems here:
fork(2)
. This is by far the most serious problem, as you are doing 100,000 forks. As your manual page will show, fork()
returns 0
in the child process, and the child's pid in the parent, if fork()
happens to execute correctly. But fork()
in your case will soon give you an error, as you cannot probably start 100,000 simultaneous processes in your system. fork()
returns -1
in case of error, and you don't check for it, so once it is unable to generate new processes, you'll end in the else
part of your if
command, considering what is an error as a successful command fork in the parent process. What this can lead is something bad, most probably.exit(3)
, instead of _exit(2)
, due to atexit()
functionallyt making it to flush stdio
buffers int both parent and child. On terminal output, this doesn't happen (you won't see this), as stdio
uses line buffering on stdout
to a terminal, so it flushes buffers before any chance to fork()
. But only if the output device is a terminal, but not if it is a file (where buffers are flushed only whe buffer is full, or at exit time, then all non-flushed stdio
buffers are flushed.) As I assume you are searching in some file, I assume you have redirected your output to a file, so a lot of repeated output is to be expected. sleep(10)
call at the end, to wait for child processes to finish, use a loop, wait(2)
ing for child processes to terminate, until you get an error from wait
. This will mean that you don't have more children alive.puts
is an example) in C++. Try to avoid them. C++ was designed to be able to use all the C language calls, so many of the legacy software is reusable and works in C++. That's true for many legacy libraries, but stdio
was superseeded a long time ago with a library (iostream
) that is far better designed (due to the new object oriented capabilities in the new language, not trying to say that Stroustrup is better than Kernighan or Ritchie, my apologies beforehand) so, using C I/O in C++ is strongly deprecated.You will see from all these comments, that your solution is not in the way you call getline()
, as you have serious problems in your code.
Upvotes: 1
Reputation: 182743
if(!(fork()))
{
// sleep(3);
puts(chunk);
exit(0);
}
This should be _exit(0);
. Otherwise, you execute the exit handlers multiple times which has unpredictable effects on things like shared file descriptors.
Upvotes: 0