I’ve got a program that I’m working on and I use select to choose from the pipes to read.
The problem is that I’m using if(FD_ISSET(pfd[i][0], &read_set)) and it fails the verification because FD_ISSET is returning 0, but if I try to read using read(pfd[i][0],&c,sizeof(c)) it will work fine and the contents from pipe pfd[0] are different from pfd[1] like I want.
I want to know what the hell is going on because FD_ISSET returns 0 but I can actually read content from it
EDIT
The global variable CORES will control how much processes I create
The next code will create the pipes and use FD_SET to set the bits
for(i=0; i<CORES; i++)
{
if(pipe(pfd[i])==-1)
perror("Ocorreu um erro a criar um pipe");
FD_SET(pfd[i][0], &read_set);
}
read_set is defined right after main() starts. I use for() right after the above code to create x processes using fork() (x = CORES)
then this part runs in father process:
while (x<CORES){
int selec = select(pfd[CORES-1][0]+1, &read_set, NULL, NULL, NULL);
if(selec>0)
{
if(FD_ISSET(pfd[x][0], &read_set))
{
close(pfd[x][1]);
if(read(pfd[x][0],&c,sizeof(c))==-1)
perror("Ocorreu um erro a ler do pipe");
printf("c= %f \n",c);
c_final+=c;
x++;
}
else
printf("\nFile descriptor pfd[%d][0] is not set\n",x);
}
else if(selec == -1)
perror("Ocorreu um erro no select");
}
the problem with this is that FD_ISSET(pfd[x][0], &read_set) will not pass because it is not set for pfd[0] but it can be for pfd[1] or vice-versa (because I don’t know if it will fail for 0 or 1)
EDIT2:
select() returns an int for the number of file descriptors in read_set. I have CORES set to 2 so it creates 2 processes and 2 pipes and sets 2 bits in read_set. my select() is returning int 1. should it be returning int 2 or 0 counts as well (so it would be 0 and 1 = 2)?
First argument of
selectis supposed to be1+max_fd. While it is likely thatpfd[CORES-1][0]is the largest, it is not guaranteed. You could calculate the largest file descriptor when you are populating theread_set, and use that for yourselectcall.Also, you need to re-populate the
read_setbefore you callselectevery single time. So the for loop outside the while loop needs to come in. Actually, it is better to move the select outside, and enclose the block starting with the for loop setting up theread_setand ending after the while loop in another loop – so that at every select return, you process all signaled descriptors without going into select again.EDIT: To clarify what I meant about the loops: you should check all descriptors every time select returns. But you cannot call select only once, as there are no guarantees that all answers will be ready at once. So you do something like: