As I noted in my comments, the problem is in the assignment pipes[pipes_count] = new_pipefd;
at:
int pipes_count = 0;
int *pipes[MAXCLIENTS];
int new_pipefd[2];
int pipe_bytes;
char pipe_buffer[MAXDATASIZE];
while(1) {
// Pipe creation
pipe(new_pipefd);
pipes[pipes_count] = new_pipefd;
pipes_count++;
The trouble is that the variable new_pipefd
is an array, so you're copying the address of the same array into each of the elements of pipes
, which means that the parent only has access to the last pipe that was created.
I think you should be using code more like:
int pipes_count = 0;
int pipes[MAXCLIENTS]; // Changed type!
int new_pipefd[2];
char pipe_buffer[MAXDATASIZE];
while (1)
{
// Pipe creation
pipe(new_pipefd);
pipes[pipes_count++] = new_pipefd[0]; // Just the read end of the pipe
if (fork())
{
// unrelated code for parent here
close(new_pipefd[1]); // close the parent's write-end of the pipe
// break; // This break is not wanted
}
else
{
// unrelated code for child here
close(new_pipefd[0]); // close the child's read-end of the pipe
break;
}
if (some condition)
break; // The parent will stop creating pipes
}
while (condition that guarantees this is the child)
{
write(new_pipefd[1], buffer, strlen(recv_buffer));
close(new_pipefd[1]);
return 0; // the child process ends
}
// This is a loop where the parent reads what the children sent
for (int i = 0; i < pipes_count; i++) {
int pipe_bytes = read(pipes[i], pipe_buffer, sizeof(pipe_buffer));
if (pipe_bytes != 0)
printf("Testing: %.*s\n", pipe_bytes, pipe_buffer); // Safe!
close(pipes[i]);
}
Were it my code, I'd have a function (which I traditionally call be_childish()
) to invoke in the 'if it is a child' block of code in the loop. The function would never return, and would be passed whatever resources it needs (new_pipefd
for sure, maybe other information too). I often have a function be_parental()
to do the parental activities. I find this cleans up most of the code, forcing clean separation of the activities.