Reputation:
The goal of my program is to create two pipes and two processes that communicate each other reading and writing to the pipes.
Until the read number from the pipe is less than BIG_INT_STOP the two processes continue to increment the number in the pipes. As soon as this condition is true, first process that reads it, close the pipes, exit and prints the number. The problem is: when the process p2 ends before p1 it works and when the process p1 ends before p2 it goes in loop. Can you explain me why?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#define BIG_INT_STOP 40
#define TEST_ERROR if (errno) {fprintf(stderr, \
"%s:%d: PID=%5d: Error %d (%s)\n", \
__FILE__, \
__LINE__, \
getpid(), \
errno, \
strerror(errno));}
int main(){
int c1[2], c2[2], p1, p2, z;
long a = 0, c;
pipe(c1);
pipe(c2);
write(c1[1], &a, sizeof(a));
write(c2[1], &a, sizeof(a));
p1 = fork();
p2 = fork();
switch(p1){
case -1:
TEST_ERROR;
exit(EXIT_FAILURE);
case 0:
read(c1[0], &c, sizeof(c));
while(c != BIG_INT_STOP){
++c;
write(c2[1], &c, sizeof(c));
read(c1[0], &c, sizeof(c));
}
close(c1[0]);
close(c1[1]);
close(c2[0]);
close(c2[1]);
printf("p1: %ld\n", c);
exit(0);
}
switch(p2){
case -1:
TEST_ERROR;
exit(EXIT_FAILURE);
case 0:
read(c2[0], &c, sizeof(c));
while(c != BIG_INT_STOP){
++c;
write(c1[1], &c, sizeof(c));
read(c2[0], &c, sizeof(c));
}
close(c1[0]);
close(c1[1]);
close(c2[0]);
close(c2[1]);
printf("p2: %ld\n", c);
exit(0);
}
while(wait(&z) != -1);
}
Upvotes: 0
Views: 139
Reputation: 8142
Your code doesn't do proper error checking on the calls to read
and write
which means that if there is a problem reading from the pipes, the child will enter a never ending loop as the value of c
will never reach the termination value.
Since your child processes close the pipes when they're done, you have a very high chance of entering a race condition where one process closes the pipes before the other has read in the latest value of c
. This is compounded by the placement of your calls to fork
as currently you end up with 3 child processes not 2.
You should move the second call to fork
after the switch
as you know that at that point you can only be in the parent process and also move the closing of the pipes to the parent.
Upvotes: 0
Reputation: 276
Problem is p2 is forked 2 times. Once in parent process, and second time in p1 process.
Instead of:
p1 = fork();
p2 = fork();
You need to write like this:
p1 = fork();
if (p1 > 0) {
p2 = fork();
}
Upvotes: 1
Reputation: 7482
Your program is a bit strange. The main problem seems to be that the second fork is executed in both main program and in the first child. In fact you are running four processes: main, two sons of main and the son of the first son. This is probably not what you want. You probably wanted to put the first switch
immediately after the first fork
and to execute the second fork
only in the main program.
And, of course, you are not checking result values of read
and write
for unexpected situations.
Upvotes: 3