Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Bad file descriptor" error when reading from pipe as stdin

Tags:

c

pipe

I fork and set up a command like this:

pid_t pid;
pid = fork();
if (pid == 0)
{   // I am the child
    freopen("/input_pipe","r",stdin);
    freopen("/output_pip","w",stdout);
    execl("/bin/sh", "sh", "-c", command, (char *)NULL); // using execv is probably faster
    // Should never get here
    perror("execl");
    exit(1);
}

The /input_pipe has been created and filled with data before the processs is forked.

This works in almost all cases absolutely fine. The command reads (with read()) from its stdin and gets the data that was written to the pipe by another process.

But sometimes the command cannot read from its stdin stream and gets the "Bad file descriptor" error when trying to do so.

What could cause this error?

Edit: I have changed the freopen parts to this:

    pipe_in = open(pipename_in, O_RDONLY);
    pipe_out = open(pipename_out, O_WRONLY);

    dup2(pipe_in, 0);
    dup2(pipe_out, 1);

I will test this for a couple of days though as the error was only appearing very seldom.

like image 798
Robby75 Avatar asked Jan 22 '14 16:01

Robby75


1 Answers

One possible source of issues is that "stdin" an "stdout" don't correspond necessarily with file descriptors 0 and 1 respectively. In many implementations of the runtime library freopen may change the file descriptor belonging to the FILE*. File descriptors belong to the kernel, while FILEs belong to the runtime library, and they are not necessarily aligned.

Please have a look here:

http://man7.org/linux/man-pages/man3/stdout.3.html

"Applying freopen(3) to one of these streams can change the file descriptor number associated with the stream"

After execl, child process only expects that file descriptor 0 and 1 are standard input and output, but it may happen that freopen closed fd 0 and connected onother fd to (FILE*)stdin. I recommend you to use the "open", "close", "dup" etc... system call and deal with file descriptors 0 an 1 directly (or, better, the standard macros STDIN_FILENO and STDOUT_FILENO).

like image 125
Giuseppe Guerrini Avatar answered Nov 14 '22 11:11

Giuseppe Guerrini