Adam Varhegyi
Adam Varhegyi

Reputation: 9924

Reading from pipe more than once

I have a parent process and a child process.

I would like to send data from my parent to my child proc.

This is how i tried:

#include<stdio.h>
#include<string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h> 
#include <signal.h>



//Handler - Exiting a process
void sigHandler(int signumber){
    printf("SIGQUIT catched.\n");
    exit(3);
}

void writeToPipe(int myData, int *pipe){

    close(pipe[0]);
    write(pipe[1], &myData,sizeof(myData));
    close(pipe[1]); 

}

int readFromPipe(int *pipe){

    int myData;

    close(pipe[1]);  
    read(pipe[0],&myData,sizeof(myData)); 
    close(pipe[0]); 

    return myData;
}

int main(){    

   int *pipefd = (int *)malloc(sizeof(int)*2);

    //Pipe Error handling
    if (pipe(pipefd) == -1){
          perror("Error on pipe init.");
           exit(EXIT_FAILURE);
     }


fflush(stdout);

char option=-1;

pid_t child_a;
pid_t child_b;

child_a = fork();

//A Child Proc which is not used atm, it will be
if (child_a == 0) {

    signal(SIGQUIT ,sigHandler); 

    while(1) {
      //idle    
        sleep(2);
        printf("child_a iddle work\n");
    }

} 

    //Child B Proc for reading form the PIPE
    else {

    child_b = fork();

    if (child_b == 0) {

        signal(SIGQUIT ,sigHandler); 

        while(1) {
        //idle
            sleep(2);
            printf("child_b iddle work\n");

            //So lets read from pipe
            int ret = readFromPipe(pipefd);
            printf("Read from pipe: %d\n", ret);

        }

    } 
    //Parent Proc for writing to a pipe 
    else {

            //MENU WHILE
            while(option!=0){

                scanf("%d", &option);
                printf("input was: %d\n", option);
                writeToPipe(option, pipefd);

            }

        }//End of Menu while

        //Exiting child prcoesses then exiting parent prcoess
        if(option==0){

            int status_a, status_b;

            waitpid(child_b, &status_b, WNOHANG|WUNTRACED);
            waitpid(child_a, &status_a, WNOHANG|WUNTRACED);

            kill(child_b,SIGQUIT); 
            kill(child_a,SIGQUIT); 

        }

    }

    return 1;

} 

Error is seen in the output:

child_a iddle work
child_b iddle work
child_a iddle work
4
input was: 4
Read from pipe: 4   ///Wow its cool i got read nicely from the pipe with my child proc
child_a iddle work
child_b iddle work
Read from pipe: -1438072844    ///Okay.. so why is it junk? but lets go ahead with an input again
child_a iddle work
child_b iddle work
Read from pipe: -1438072844
child_a iddle work
1
input was: 1                 //Input again, it is 1
child_b iddle work
Read from pipe: -1438072844     //Read from pipe remains the same junk, and not 1, why?
child_a iddle work
child_b iddle work
Read from pipe: -1438072844
child_a iddle work
3
input was: 3                       //Same here with 3
child_b iddle work
Read from pipe: -1438072844
child_a iddle work
0
input was: 0                     //I exit with 0, that is okay.
SIGQUIT catched.
SIGQUIT catched.

I searched a lot but coudnt find a solution, i only found examples with only one data sent in pipe and not many.

Upvotes: 0

Views: 1608

Answers (1)

user1999073
user1999073

Reputation: 106

Its because your readFromPipe and writeToPipe methods are closing the file descriptors for the read and write ends of the pipe each time they are called. Take those statements out from those methods and you should stop getting bad output (which I assume was triggered by an uncaught error by either close(), read(), or write() because they were trying to operate on an already closed file descriptor).

Another thing to consider would be to close the pipe fd's for both ends of the pipe in child_a as the extra references are useless if parent doesnt need to write to child_a using the same pipe as well as closing the ends of the pipe that child_b and parent don't need access to (e.g. parent doesn't need read access, child doesn't need write access)

Upvotes: 2

Related Questions