views:

2691

answers:

2

Hello,

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;
     }
    }
}
A: 

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.

+2  A: 

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.

mweerden