michal
michal

Reputation:

Broken pipes in C -- pipe(), fork(), exec() program

I need to write a simple program: There will be a Parent and a few programs [children] (started via execl in Parent). Children communicate to one another in this way: Child I sens to Parent number J, Parent sends a message (something like -- "there is a message to you") to J, J send to Parent number K etc. etc.

And there is a problem -- my program (tested by strace command) tries to send a message to child and there comes the broken pipe error.

I will be grateful if somebody looks through the code and tells me what's wrong:

Here is the code:

/**
 * Arbiter zabawy w Losia
 *

 wersja: Alfa 3b
 początek edycji 25.01.2009
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "err.h"

pid_t pid;
FILE *a;

int main ()
{
    // my N players
    int N;
    N = 10;
    //write -- writing from parent to child 
    //read -- reading from child
    int rurka_write[N+1][2]; 
    int rurka_read[N+1][2];
    //initiation of N players
    int i;
    for(i = 1; i <= N; i++)
    {
        //tworze lacza
        if (pipe(rurka_write[i]) == -1)
            printf("wystapil blad przy rurce %d\n", i);
        if (pipe(rurka_read[i]) == -1)
            printf("wystapil blad przy rurce %d\n", i); 
    }
    for(i = 1; i <= N; i++)
    {
        switch(pid = fork())
        {
            case -1: 
                printf("wystapil blad przy forkowaniu");
            case 0:
                printf("potomek numer %d\n", i);
                if (close(rurka_write[i][1]) == -1)
                    printf("zle zamykanie");
                if (close(rurka_read[i][0]) == -1)
                    printf("zle zamykanie");

                //closing useless descriptors
                int j;
                for(j = 1; j <= N; j++)
                {
                    if (j != i)
                    {
                        close(rurka_read[j][0]);
                        close(rurka_read[j][1]);
                        close(rurka_write[j][0]);
                        close(rurka_write[j][1]);
                    }
                }   

                char str_N[20];
                char str_i[20];
                char str_0[20];
                char str_1[20];

                sprintf(str_N, "%d", N);
                sprintf(str_i, "%d", i);
                sprintf(str_0, "%d", rurka_write[i][0]);
                sprintf(str_1, "%d", rurka_read[i][1]);

                printf("%d Executing execl\n", i);
                execl("./ucz", str_N, str_i, str_0, str_1, NULL);
                printf("execl executed\n");
//              execv("./ucz", str_N, str_i, str_0, str_1, NULL);
                //exit(0);
            default:
                //closing useless pipes
                if (close(rurka_read[i][1]) == -1)
                    printf("zle zamykanie rurki do czytania z potomkna\n");
                if (close(rurka_write[i][0]) == -1)
                    printf("zle zamykanie rurki do pisania do potomka\n");
        } //end of switch

    } //end of for
    //if I am in parent, I'm starting the game
    if (pid != 0)
//  delay(100);
    {
        printf("PLAY\n");
        int l = 1;
        while(l > 0)
        {
            printf("sending to player %d\n", l);
            a = fdopen(rurka_write[l][1], "w");
            printf("sending: Wake up");
            fprintf(a, "Wake up\n");
            printf("flushing");
            fflush(a);
            char k[20];
            printf("reading");
            read(rurka_read[l][0], k, 20);
            l = k;
        }
    }
}

Upvotes: 1

Views: 6033

Answers (2)

mweerden
mweerden

Reputation: 14061

Besides the fact that you do not end your cases with a break (as noted by strager), the main problem is the statement l = k;. Note that k is a char[20] and, when assigned to a int, you don't assign any of the contents of k to l. Instead l will contain (the value of) the pointer to the array. You will have to do something different here to get the value that is in the array; what exactly depends on that ucz sends back.

After fixing this and making my own ucz, the program seems to work without any problem. Of course, it might also be that there is another problem in your version of ucz.

Upvotes: 2

michal
michal

Reputation:

About ./ucz -- it takes 4 parameters -- 1st -- number of players, 2nd -- player number, 3rd -- number of descriptor to read from parent, 4th -- number of descriptor to write to parent.

Adding exit(0), return(0), break after exec (or in the end of "case: 0") doesn't help.

Upvotes: 0

Related Questions