'Two way communicating with pipes - in the correct order
I have a small program to demonstrate two way communication with pipe between parent and child processes. I already asked a question about this (Two way communicating using pipe).
So I have a parent process and two child processes (child_a, child_b). I use 4 pipes for communicating between processes: pipefd_a1 and pipefd_b1 for parent-child, pipefd_a2 and pipefd_b2 for child-parent communicating. First the parent calculating some data and collecting these in two arrays (rabbits_a and rabbits_b). These arrays containing struct Rabbit elements. Then the parent process sends rabbits_a to child_a and rabbits_b to child_b. The child processes process the sent data then send back to parent. Everything is working fine until this moment. When parent comes to read these datas the program just hangs and seems like it never returns from the while (read) loop. I'm sure that I close all the pipes correctly, but I think the problem is that I'm closing one of the pipes at the wrong time.
Can anyone help me what the problem could be?
The relevant code snippet:
int pipefd_a1[2], pipefd_a2[2];
int pipefd_b1[2], pipefd_b2[2];
pid_t child_a, child_b;
if (pipe(pipefd_a1) != 0 || pipe(pipefd_a2) != 0 || pipe(pipefd_b1) != 0 || pipe(pipefd_b2) != 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
//
// Calculating the datas to send
//
Rabbit** rabbits_a = (Rabbit**)malloc(sizeof(Rabbit*) * size);
unsigned count_a = 0;
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL && (strcmp("Barátfa", iterator[i]->district) == 0 || strcmp("Lovas", iterator[i]->district) == 0 || strcmp("Kígyós-patak", iterator[i]->district) == 0 || strcmp("Káposztás kert", iterator[i]->district) == 0)) {
rabbits_a[count_a++] = add_rabbit(iterator[i]->name, iterator[i]->district, iterator[i]->part_count, iterator[i]->eggs_count);
}
}
Rabbit** rabbits_b = (Rabbit**)malloc(sizeof(Rabbit*) * size);
unsigned count_b = 0;
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL && (strcmp("Szula", iterator[i]->district) == 0 || strcmp("Malom telek", iterator[i]->district) == 0 || strcmp("Páskom", iterator[i]->district) == 0)) {
rabbits_b[count_b++] = add_rabbit(iterator[i]->name, iterator[i]->district, iterator[i]->part_count, iterator[i]->eggs_count);
}
}
if ((child_a = fork()) < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (child_a == 0) { // Child A
close(pipefd_b1[0]);
close(pipefd_b1[1]);
close(pipefd_b2[0]);
close(pipefd_b2[1]);
close(pipefd_a1[1]);
close(pipefd_a2[0]);
// Receiving data from parent
Rabbit* rabbits = (Rabbit*)malloc(sizeof(Rabbit) * size);
Rabbit rabbit;
unsigned count_rabbits = 0;
while (read(pipefd_a1[0], &rabbit, sizeof(Rabbit))) {
rabbit.eggs_count = rand() % 100 + 1;
rabbits[count_rabbits++] = rabbit;
}
close(pipefd_a1[0]);
// Sending data back to parent
for (unsigned i = 0; i < count_rabbits; ++i) {
write(pipefd_a2[1], &rabbits[i], sizeof(Rabbit));
}
close(pipefd_a2[1]);
} else if ((child_b = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (child_b == 0) { // Child B
close(pipefd_a1[0]);
close(pipefd_a1[1]);
close(pipefd_a2[0]);
close(pipefd_a2[1]);
close(pipefd_b1[1]);
close(pipefd_b2[0]);
// Receiving data from parent
Rabbit* rabbits = (Rabbit*)malloc(sizeof(Rabbit) * size);
Rabbit rabbit;
unsigned count_rabbits = 0;
while (read(pipefd_b1[0], &rabbit, sizeof(Rabbit))) {
rabbit.eggs_count = rand() % 100 + 1;
rabbits[count_rabbits++] = rabbit;
}
close(pipefd_b1[0]);
// Sending data back to parent
for (unsigned i = 0; i < count_rabbits; ++i) {
write(pipefd_b2[1], &rabbits[i], sizeof(Rabbit));
}
close(pipefd_b2[1]);
} else { // Parent
// Sending data to child_a
for (unsigned i = 0; i < count_a; ++i) {
Rabbit rabbit = {rabbits_a[i]->name, rabbits_a[i]->district, rabbits_a[i]->part_count, rabbits_a[i]->eggs_count};
write(pipefd_a1[1], &rabbit, sizeof(Rabbit));
}
close(pipefd_a1[1]);
// Sending data to child_b
for (unsigned i = 0; i < count_b; ++i) {
Rabbit rabbit = {rabbits_b[i]->name, rabbits_b[i]->district, rabbits_b[i]->part_count, rabbits_b[i]->eggs_count};
write(pipefd_b1[1], &rabbit, sizeof(Rabbit));
}
close(pipefd_b1[1]);
// Receiving data from child_a
Rabbit rabbit;
while (read(pipefd_a2[0], &rabbit, sizeof(Rabbit))) {
modify(rabbit.name, rabbit.district, rabbit.part_count, rabbit.eggs_count);
}
// Doesn't reach this point
close(pipefd_a2[0]);
// Receiving data from child_b
while (read(pipefd_b2[0], &rabbit, sizeof(Rabbit))) {
modify(rabbit.name, rabbit.district, rabbit.part_count, rabbit.eggs_count);
}
close(pipefd_b2[0]);
close(pipefd_a1[0]);
//close(pipefd_a1[1]);
//close(pipefd_a2[0]);
close(pipefd_a2[1]);
close(pipefd_b1[0]);
//close(pipefd_b1[1]);
//close(pipefd_b2[0]);
close(pipefd_b2[1]);
int corpse;
int status;
while ((corpse = wait(&status)) > 0) {
printf("Child %d exited with status 0x%.4X\n", corpse, status);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
