0

Hi I've to develop this program that create 4 children and, sequentially, make 'em do a simple operation. The first will do the sum, the second the rest, the third the multiplication and the fourth the division. The father will write on the socket the string with the two number he wants his children to "calculate", and every children should read this string, extract the numbers and to the operations. Obviously, being two pipes, it's needed that the father writes every time the string, because of the read in the child. I don't really understand why at the second iteration, i receive a SIGPIPE on the write of the father. Can someone explain me why? I losed 3 days on debugging, but I didn't find anything. Thank you very much.

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

/*
fd_0 padre escribe y hijo lee ==== padre cierra fd_0[0] y hijo cierra fd_0[1]
fd_1 hijo escribe y padre lee ===  padre cierra fd_1[1] y hijo cierra fd_1[0]
*/


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


    char * str = malloc(100*sizeof(char));//hijo
    char readbuffer_h[150];

    char * stringa = malloc(100*sizeof(char));//padre
    char readbuffer_p[150];


    int a,b;
    int x,y;
    int n = 4;
    int i,status,nbytes, pipe_status;
    int pid, ppid,yo,padre;
    int fd_0[2], fd_1[2] ;



    pipe_status=pipe(fd_0);
    if(pipe_status==- 1) {
        perror("Error creando la tuberia 0\n");
        exit(EXIT_FAILURE);
    }


    pipe_status=pipe(fd_1);
    if(pipe_status== -1) {
        perror("Error creando la tuberia 1 \n");
        exit(EXIT_FAILURE);
    }   



    for(i=0; i< n; i++){

        if ((pid=fork()) <0 ){
        printf("Error al emplear fork\n");
        exit(EXIT_FAILURE);
        }

/*-------------------------------------------------------------------------------------------------------------------------------------------------*/

        else if (pid ==0){// soy el hijo


            yo = getpid();
            padre = getppid();
            printf("HIJO: %d, mi padre es: %d\n", yo, padre);    

            close(fd_0[1]);
            close(fd_1[0]);

            //TODO


            nbytes = read(fd_0[0], readbuffer_h, sizeof(readbuffer_h));

            sscanf(readbuffer_h, "%d,%d", &x, &y);


            switch(i) {

                case 0 :
                    //TODO
                    sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La suma es %d", yo,x,y,(x+y));
                    break;

                case 1 :
                    //TODO
                    sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La resta es %d", yo,x,y,(x-y));
                    break;          

                case 2 :
                    //TODO
                    sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El producto es %d", yo,x,y,(x*y));
                    break;

                case 3 :
                    //TODO
                    sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El cociente es %d", yo,x,y,(x/y));
                    break;

            }


            write(fd_1[1], str, strlen(str));


            exit(EXIT_SUCCESS); 
        }

/*-------------------------------------------------------------------------------------------------------------------------------------------------*/


        else{ //soy el padre
            yo = getpid();
            printf("PADRE:%d\n", yo);

            a = 3; b = 4;

            close(fd_0[0]);
            close(fd_1[1]);


            sprintf(stringa,"%d,%d",a,b);
            printf("Stringa padre : %s\n", stringa);
                fflush(stdout);

            write(fd_0[1],stringa,strlen(stringa)); // questa write non va a buon fine


            wait(&status);

            read(fd_1[0], readbuffer_p, sizeof(readbuffer_p));
            printf("%s\n",readbuffer_p);
                fflush(stdout);

        }


    }

close(fd_0[0]);
close(fd_0[1]);
close(fd_1[0]);
close(fd_1[1]);


return 0;
}

1 Answers1

1

You're getting yourself into trouble by trying to use the same pipes to communicate with each child.

You create two pipes at the beginning of the program. On the first iteration of the loop, the parent forks, and the child inherits all the parent's open file descriptors. The child closes the pipe ends it doesn't need, and the parent closes the pipe ends it doesn't need. Communication happens as intended (I imagine) -- all well and good so far.

But now consider the second iteration of the loop. You fork again, and the child again inherits the parent's open file descriptors. But now, the file descriptors the child wants to use were closed by the parent in the previous iteration of the loop. I'm a bit surprised that the child then gets an EPIPE instead of an EBADF when it tries to use those file descriptors, but I'm not at all surprised that its read attempt fails.

The cleanest thing to do would be to create a new pair of pipes for each child, instead of trying to reuse one set of pipes. If you want to make it work with just the one pair, then the parent process must avoid closing any of the pipe ends (though the child processes may close their copies, if you wish).

John Bollinger
  • 160,171
  • 8
  • 81
  • 157