i am trying to send the data from server child processes to the clients. i am storing first client fd in ids[0] and seconds one in ids[1] then i am trying to send the data from first child process to another client and vic-e-versa.
i get bad file descriptor error.
//ids are defined at the begining as follows
int *ids = (int *) mmap(NULL,5*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//accept is in a for loop...
mysocket = accept(sock, NULL, NULL);
printf("\nClient connected ...\n ");
ids[i]=mysocket;
i++;
printf(" socket and id %d %d",mysocket,ids[i-1]);
int pid = fork();
if (pid == 0) {
if (mysocket < 0) {
perror("Error in accept");
exit(1);
}
do {
fflush(stdout);
//clearing the bufffer
//memset(&buf[0], 0, sizeof(buf));
//memset(buf, sizeof(buf), '\0');
//reading message on the socket.
if(i==1)
if(send(ids[1], buf, 1024,0)==-1){
perror("error in i=1");
printf("%d %d %d",mysocket,ids[0],ids[1]);
}
if(i==2) {
if(send(ids[0], buf, 1024,0)==-1) {
perror("error in i=2");
printf("%d %d %d", mysocket, ids[0], ids[1]);
}
}
if (strcmp(buf, "CLOSE") == 0) {
close(mysocket);
break;
}
} while (1);
Error i get : error in i=1: Bad file descriptor 4 4 5
the values 4 and 5 are of the fds and that are correctly stored and i am not closing the sockets anywhere.
Your code is badly formatted and I hope I interpret it correctly.
ids[i]=mysocket;
i++;
If i
was 0
then ids[0]
is now valid, ids[1]
is still invalid (i.e. has some arbitrary value which might look valid but is not) and i
is now 1
. With i==1
the child runs into this code (after proper formatting):
if(i==1)
if(send(ids[1], buf, 1024,0)==-1){
perror("error in i=1");
printf("%d %d %d",mysocket,ids[0],ids[1]);
}
As you can see, it uses send(ids[1]...
. But as explained above with i==1
only ids[0]
has a valid value and the value in ids[1]
is invalid. Therefore the send
fails with Bad file descriptor
.
My guess is that you assume that a file descriptor created in the master process is actually valid in all child process since you are trying to use a shared array (with MAP_SHARED
) between the childs and the master:
int *ids = (int *) mmap(NULL,5*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
But this assumption is wrong. File descriptors are not propagated into all child processes but only propagated on fork to the new child. This means your first child will have a valid file descriptor in fds[0]
only while the second child will have a valid file descriptor in both fds[0]
and fds[1]
. The fact that the first child will see the same file number in fds[1]
as the second child due to the shared array does not mean that this file number is also associated with a valid (in-kernel) file descriptor.
Note that it is very useful to actually document the intention of your code in your code. This way others can better understand your code and all (including you) can better verify if the intention actually matches the implementation.