cpipefile-descriptorfdopen

Bad file descriptor when using fdopen?


I have the folowing C code. The child is used to run test3, whose code will be below. The parent is used to pass the data to the child which will be redirected to STDIN of test3.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char *argv[]) {
    int fd[2];
    char buf[] = "HELLO WORLD!";
    if(pipe(fd)){
      perror("pipe");
      return -1;
    }
    switch(fork()){
        case -1:
            perror("fork");
            return -1;
        case 0:
            // child
            close(fd[1]);
            dup2(fd[0], STDIN_FILENO);
            close(fd[0]);
            system("./test3");
        default:
            // parent
            close(fd[0]);
            FILE* stream = fdopen(fd[1],"w");
            if(stream == NULL){ // error checking
                printf("Error creating a file\n");
                printf("%s\n", strerror(errno));
                return -1;
            }
            // write data to pipe
            fwrite(buf, 1,6,stream);
            close(fd[1]);
            fclose(stream);
    }
    printf("END~\n");
    return 0;
}  

And here is test3 code:

#include <stdio.h>
int main(){
     char n[1000];
     scanf("%s",n);
     printf("%s\n",n);
}

My problem is the fdopen in the parent's code returns NULL with the Bad file descriptor error and I cannot figure out the reasons. Can anyone helps?

Thanks in advance.


Solution

  • The error is actually coming from the child, not the parent. After the child runs test3 with the system call, it falls through into the default: case, trying to fdopen the file descriptor it has already closed. Add break; after the system call and the error will go away.

    A second problem is the close(fd[1]) in the parent, which closes the file descriptor out from under the FILE pointer before it flushes the data you wrote with fwrite. Either put an fflush(stream); call before the close or just get rid of the close, as the fclose will close the file descriptor.