'Multi Thead by using fork() with shared pipe, data sometimes get overwritten by different Child before read

int main(int argc, char **argv)
{
    int k=0,i=0;
    int status;
    char x[100],a[100];
    int fd[2];
    pipe(fd);
    //printf("number = %d\n",argc);
    for(i=1;i<argc;i++){
        if(fork()==0){
            //printf("Child pid=%d\n",getpid());
            close(fd[0]);
            double s,temp=0.0;
            int count=0;
            FILE *file;
            file = fopen(argv[i], "r");
            //printf("!!!Handle file %s\n",argv[i]);
            while(!feof(file)){
                //printf("--Scaning\n");
                fscanf(file,"%lf ",&temp);
                s+=temp;
                count++;
                //printf("++Counting:%d\n",count);
            }
            printf("Child PID=%d of Parent PID=%d, finished handle file %s with sum=%lf and count=%d.\n",getpid(),getppid(),argv[i],s,count);
            sprintf(a,"%lf %d %s",s,count,argv[i]);
            //printf("%s + %s",a,argv[i]);
            fclose(file);
            write(fd[1], a, (strlen(a)+1));
            close(fd[1]);
            return 0;
        }
        //else{
            //printf("Total: %d\n",argc);
        //}
    } 
        close(fd[1]);
        int countsum,tempcount=0;
        double tempsum,ave,sum=0.0;
        char name[100];
        for (i = 1; i < argc ; i++){
            //printf("\nParent PID=%d, and now Waiting.\n", getpid());
            //wait(&status);
            //printf("Child Exit Code = %d\n\n",status);
            read(fd[0],x,sizeof(x));
            sscanf(x,"%lf %d %s",&tempsum,&tempcount,name);
            printf("%s SUM=%lf NUM=%d AVG=%lf\n",name,tempsum,tempcount,tempsum/tempcount);
            sum+=tempsum;
            countsum+=tempcount;
        }
        printf("AVERAGE=%lf\n",sum/countsum);
    return 0;
}

Source Code attached, sometimes child process will overwrite the result from other child before that result getting read, I can not use a static number of pipes since the question require the code work with any number of input.

dataset1 SUM=8212.128970 NUM=171 AVG=48.024146 
dataset2 SUM=5386.242610 NUM=99 AVG=54.406491 
dataset3 SUM=6845.298770 NUM=135 AVG=50.705917 
AVERAGE=50.478198

Some times it gets things like this:

dataset2 SUM=5386.242610 NUM=99 AVG=54.406491
dataset3 SUM=6845.298770 NUM=135 AVG=50.705917
dataset3 SUM=6845.298770 NUM=135 AVG=50.705917

[root@localhost CacheDrive]#

Output



Solution 1:[1]

Solved by assigning a fixed value for write and read size, like this?

char x[MAXARGU_SIZE*argc];
char a[MAXARGU_SIZE];

and scan the results by a char* which move right by MAXARGU_SIZE each time? read results one by one. like such

for (i = 1; i < argc ; i++){
        wait(NULL);
    }
    int scaning=0;
    char* ptc=x;
    read(fd[0],x,sizeof(x));
    for (i = 1; i < argc ; i++){
        //printf("\nParent PID=%d, and now Waiting.\n", getpid());
        //wait(&status);
        //printf("Child Exit Code = %d\n\n",status);
        scaning+=MAXARGU_SIZE;
        sscanf(ptc,"%lf %d %s\0",&tempsum,&tempcount,name);
        ptc=&x[scaning];
        printf("%s SUM=%lf NUM=%d AVG=%lf\n",name,tempsum,tempcount,tempsum/tempcount);
        sum+=tempsum;
        countsum+=tempcount;
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Kenren98