-
fork behavior
Running the following code:
Code:
int run_execve ( int cid );
int so_far = 0;
int MAX_PROCS = 1000; /* create this many processes */
int main(void) {
int cid;
printf ( "C\n" );
while ( so_far < MAX_PROCS ) {
/* attempt to run an executable */
cid = fork();
run_execve ( cid );
printf ( "A\n" );
so_far++;
}
}
int run_execve ( int cid ) {
if ( cid == 0 ) {
exit ( -1 );
}
}
I would expect to see a single C in the output, and 1000 A's. Instead, I'm getting 72 C's and 3485 A's. This behavior makes no sense to me. Eventually, I plan to call execve from within the run_execve method, but do to the current problems, I've cut it out until I can get fork under control.
-
"fork" basically creates a copy of the current process, including copies of all of its variables, etc.. So, for example, at the start of the first iteration of the "while" loop, there is just one one copy of all of its data, such as 'cid'. In particular, each process has references to the standard streams (STDOUT, STDERR, STDIN). If they didnt, you wouldnt be able to use "printf" or "scanf", because these use the 2 default out/in streams. One important thing is that 'printf' writes to STDOUT, which is buffered. This means that the output might be unpredictable, except when you force it to print, i.e. "flush" or the stream is closed or process ends, etc.
So your first printf statement before the while loop writes something to the buffer of STDOUT (though nothing is actually printed, yet). Next, inside the while loop you fork. You now have 2 processes, each with their own "STDOUT" buffer which (maybe or maybe not!) has the "C" in it. So when the OS eventually gets around to actually printing the stuff, theres "C\nC\n" in the buffer. This is in addition to the things that the other processes (forked children) write to this buffer. So on different runs of the program, there might even be different ordering of output, as the process scheduling isnt reliable either (unless you forced it to be, i.e. synchronized it).
Two solutions:
1) Write to an unbuffered stream. Basically change your "printf"s to "frprintf" to "stderr", which is unbuffered. Therefore any writes to it will happen "immediately" and reliably.
2) "flush" "stdout" after every "printf".
In either case you should get the expected number of characters each outputted.
-
Thank you nadroj. Your reply fixed the problem.
Consequently, for anyone else that finds this problem, you get different behavior using _exit versus exit depending on whether or not there is a printf statement before the exit call. Be sure to read the man page for exit carefully to understand why this is the case.