Search code examples
clinuxpipenamed-pipes

FIFO read() function gets stuck in c


I'm trying to read a text file's string from a process, then deliver the string to another process via named pipes on LINUX. The problem is when i type './reader text.txt = receiver' to the console the recieving process' read() function returns an error if i put the line

fcntl(fd, F_SETFL, O_NONBLOCK);

or gets stuck on read() function if i remove it.

heres the process that reads the string (reader)

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

 int main(int argc,char *argv1[]){

 if(argc==4 && strcmp(argv1[2],"=") == 0){

 char mesaj[99999]; //message to be delivered

    char line[150];
    FILE *fp =fopen(argv1[1],"r");  //reading from a text file

    if(fp==NULL){

        printf("text file error!");
        exit(1);
    }


    while(fgets(line,sizeof(line),fp)){
        strcat(mesaj,line); //append every line to message

    }

    fclose(fp);

    mesaj[strlen(mesaj)-1]='\0';

    int n =strlen(mesaj)+1;


   //printf("got the text  %s\n",mesaj);


    if(mkfifo("myFifo",0777)== -1 && errno!= EEXIST){ 
        printf("Pipe error");
        exit(1);
    }


    printf("opening\n");
    int fd= open("myFifo",O_RDWR);
    if(fd==-1){
        printf("open error");
        exit(1);
    }
    printf("opened");


    if( write(fd, mesaj,sizeof(char)*n)==-1){
        printf("write error");
        exit(1);
    }


    printf("written");

    close(fd);

    printf("closed");
    fflush(stdout);


   char mesajSizeChar[n];
   sprintf(mesajSizeChar, "%d", n);


    char *args[]={mesajSizeChar,NULL}; //send the message size as parameter for the other process
    char program[]="./";
    strcat(program,argv1[3]); // recieved process name as parameter
    execv(program,args); // call the other process
    perror("execv");


    return 0;
     }
 }

and heres the recieving process (reciever)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>

int main(int argc,char *argv1[]){

int mesajSize=atoi(argv1[0]); //convert message size to integer
char mesaj[99999];

printf("\ncame here\n");


int fd= open("myFifo",O_RDWR);
fcntl(fd, F_SETFL, O_NONBLOCK);
printf("\nopen \n");

if(fd==-1)
    printf("pipe error\n");


if(read(fd,mesaj,sizeof(char)*mesajSize)==-1)
printf("read error\n");


printf("read \n");
printf("\nworked: %s \n",mesaj);

close(fd);
return 0;

 }

Solution

  • The problem is that you closed the pipe in the first process. A pipe doesn't have any permanent storage, it can only hold data while it's open by at least one process. When you close the pipe, the data that you've written to it is discarded.

    As a result, when the second process tries to read from the pipe, there's nothing available.

    You need to keep the pipe FD open when you execute the second process. Get rid of close(fd); in the reader program.