Reputation:
so I am working on this C code, that print a list of child PID and parent PID
the problem that my output looks like this
digraph {
"12896" [ label="pid 12896, level 0" ];
"12897" [ label="pid 12897, level 1" ];
"12896" -> "12897";
"12898" [ label="pid 12898, level 2" ];
"12897" -> "12898";
"12899" [ label="pid 12899, level 3" ];
"12898" -> "12899";
"12900" [ label="pid 12900, level 4" ];
"12899" -> "12900";
}digraph {
"12896" [ label="pid 12896, level 0" ];
"12897" [ label="pid 12897, level 1" ];
"12896" -> "12897";
"12898" [ label="pid 12898, level 2" ];
"12897" -> "12898";
"12899" [ label="pid 12899, level 3" ];
"12898" -> "12899";
digraph {
"12896" [ label="pid 12896, level 0" ];
"12897" [ label="pid 12897, level 1" ];
"12896" -> "12897";
"12898" [ label="pid 12898, level 2" ];
"12897" -> "12898";
digraph {
"12896" [ label="pid 12896, level 0" ];
"12897" [ label="pid 12897, level 1" ];
"12896" -> "12897";
digraph {
there is 4 different digraph object, I only need the first one. also I am not sure why the first line inside digraph is tabbed, if anyone knows
here is the C code of my fork
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){
int i, status;
printf( "Enter a value for n :");
int n;
scanf("%d", &n);
FILE *file;
file = fopen("./diagraph.txt", "w+"); //my output file
fprintf(file, "digraph {\n");
for (i=0; i<=n; i++){
//fflush(stdout);
int pid = fork();
if (pid == 0 ) {
if(i == 0){ //first level
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getppid(), getppid(), i, file);
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i +1, file);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid(), file);
}else{
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i +1, file);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid(), file);
}
}
else{ //parent process, we will wait for the children.
pid = waitpid(-1, &status, 0);
return 0;
}
}
fprintf(file, "}");
fclose(file);
}
I am not sure of the reason of this behavior, I would like to understand it and know how to fix it thank you in advance
Upvotes: 0
Views: 225
Reputation: 182779
While a process is executing, it may need to arrange to have a number of tasks performed when that process terminates. When you call fork
, the child process inherits this arrangement from the parent. If the child process terminates normally, it will execute this list of tasks.
In general, there is no way for someone writing application code to know what's on this list. It's managed by system libraries and can contain very platform-dependent things. In this case, it's flushing standard library buffers to the file.
It is extremely important that you not let both a parent process and a child process terminate normally unless you have some way to know that this duplication of possible exit tasks created in the parent will not cause a problem. Serious bugs involving significant compromises to security-sensitive information have occurred because this has been ignored.
The simplest solution is to ensure that all processes but the initial one terminate by calling _exit
. If you write to any streams in the child, you need to fflush
them before the fork
and fclose
them in any child that used them before calling _exit
.
You can, and should, use fflush
if a stream is going to be accessed in both the parent and the child processes. But don't think that just because you called fflush
that means it's safe to let the child terminate normally. There is no way to know (without looking closely into the particular platform's standard library implementation) what that will do.
Upvotes: 0
Reputation: 126243
By default, when you write to a file with fprintf
it doesn't actually write to the file (yet) -- it just writes to a buffer. When the buffer fills up, or you later call fflush
or fclose
, then the data in the buffer is written to the file. The buffer is part of the FILE object stored in memory of the process, so when you call fork
, the buffer and it's contents are duplicated. This results in a situation where both the child and parent may write the same data into the file, resulting in duplication.
The easiest way to avoid this is to ensure you call fflush
on all FILE
objects you have before calling fork, so that the buffers are all empty and no data is duplicated.
Upvotes: 1