Updated Named Pipes in C | Can't always get what i expect

43 views Asked by At

I'm currently working on a project involving 4 processes that communicate through named pipes. However i don't ALWAYS get the results i expect. Writers are just sending an int equal to the process pid.

Here is a short executable code i made to illustrate my problem :

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>

int main(void){
int i, j, k, pid;
int childs = 4;
int size = 16;
char nomTube[size];

for(j = 0; j < childs; j++)
{
sprintf(nomTube, "assistant%d.fifo", j);
if(mkfifo(nomTube, 0777) != 0) 
{
    fprintf(stderr, "Impossible de créer le tube nommé.\n");
    //exit(EXIT_FAILURE);
}
}

for(i = 0; i < childs; i++)
{
if(fork() == 0)
{
    pid = i;
    if(pid % 2 == 0)
        {Writing(pid); printf("Child(%d) writing done;\n", pid);}
    else
        {Reading(pid); printf("Child(%d) reading done;\n", pid);}
    break;
}
}

for(k = 0; k < childs; k++)
{
wait(NULL);
}

return 0;}

Now the Writing function :

void Writing(int pid){
int entreeTube;
int var = pid;
int i;
if(pid == 0)
{
for(i = 0; i < 2; i++)
{
    printf("Child(%d) i'm writing to Child(%d) var = %d;\n", pid, 1, var);
    if((entreeTube = open("assistant1.fifo", O_WRONLY)) == -1) 
    {
        fprintf(stderr, "Impossible d'ouvrir l'entrée du tube nommé.\n");
        //exit(EXIT_FAILURE);
    }
    write(entreeTube, &var, sizeof(int));
}
}
else if(pid == 2)
{
for(i = 0; i < 2; i++)
{
    printf("Child(%d) i'm writing to Child(%d) var = %d;\n", pid, 3, var);
    if((entreeTube = open("assistant3.fifo", O_WRONLY)) == -1) 
    {
        fprintf(stderr, "Impossible d'ouvrir l'entrée du tube nommé.\n");
        //exit(EXIT_FAILURE);
    }
    write(entreeTube, &var, sizeof(int));
}
}}

Now the Reading function :

void Reading(int pid){
int sortieTube;
int var = -1;
int i;

if(pid == 1)
{
for(i = 0; i < 2; i++)
{
    if((sortieTube = open ("assistant1.fifo", O_RDONLY)) == -1) 
    {
        fprintf(stderr, "Impossible d'ouvrir la sortie du tube nommé.\n");
        //exit(EXIT_FAILURE);
    }

    read(sortieTube, &var, sizeof(int));
    printf("Child(%d) var = %d\n", pid, var);
}
}
else if(pid == 3)
{
for(i = 0; i < 2; i++)
{
    if((sortieTube = open ("assistant3.fifo", O_RDONLY)) == -1) 
    {
        fprintf(stderr, "Impossible d'ouvrir la sortie du tube nommé.\n");
        //exit(EXIT_FAILURE);
    }

    read(sortieTube, &var, sizeof(int));
    printf("Child(%d) var = %d\n", pid, var);
}
}}

So basically :

  • Child(0) writes to "assistant1.fifo" 2 times | writes 0
  • Child(2) writes to "assistant3.fifo" 2 times | writes 2
  • Child(1) reads "assistant1.fifo" 2 times | reads 0
  • Child(3) reads "assistant3.fifo" 2 times | reads 2

Sometimes it works but some other times it just blocks. You might have to execute a few times to see it block though.

Is this a sync problem? Even though writing/reading are blocking?

I don't see where the problem is... so i think i'm missing something related to the pipe mechanics. Do you see what's wrong ?

My apologies for the code editing and indentation, and also for my english, i hope you understand me good enough.

1

There are 1 answers

0
Jonathan On

I believe i found the awnser. I resolved the problem by opening only once the mkfifo both in writing and reading. Then comes the loop wich writes or reads.

    printf("Child(%d) i'm writing to Child(%d) var = %d;\n", pid, 1, var);
    if((entreeTube = open("assistant1.fifo", O_WRONLY)) == -1) 
    {
        fprintf(stderr, "Impossible d'ouvrir l'entrée du tube nommé.\n");
        //exit(EXIT_FAILURE);
    }
    for(i = 0; i < 2; i++)
    {
        write(entreeTube, &var, sizeof(int));
    }

Same thing for the reading process. Even though it is working just fine, if someone knows the mechanics behind all this and can explain them i would be grateful. Thank you very much :)