Home > Back-end >  Redirecting stdout to pipe and reading from it from a single process
Redirecting stdout to pipe and reading from it from a single process

Time:10-16

I'm porting a Linux program to a system which has no fork(), so everything runs in a single process. This program creates pipe, redirects stdout to pipe's input, forks, children calls printf and parent reads data from pipe. I removed fork, and tried to test it on Linux - the program is hanged on read() which waits for data on pipe. Here's a small reproducer:

#include <stdio.h>
#include <unistd.h>
const char in[7] = "qwerty";

int main ()
{
    int fds[2], stdout_sav;
    char str[8] = {0};
    pipe(fds);
    if ((stdout_sav = dup(1)) < 0) return 1;  // save stdout
    if (dup2(fds[1], 1) < 0) return 2;   // stdout -> pipe
    close(fds[1]);

    if (printf(in) <= 0) return 3;
    //fsync(1);        // behavior does not change if I add a fsync here
    read(fds[0], str, sizeof(in));    // HERE: read waits for data
    close(fds[0]);
    if (dup2(stdout_sav, 1) < 0) return 4;   // restore stdout
    close(stdout_sav);

    printf("Received %s\n", str);
    return 0;
}

As it does not work on Linux, I suppose there is wrong logic in the code, but I don't see any problems with it.

I had an idea that a single process won't write to pipe if there are no readers, however, this is not true as the following code works OK:

    pipe(fds);
    write(fds[1], in, sizeof(in));
    close(fds[1]);
    read(fds[0], str, sizeof(in));
    close(fds[0]);
    printf("Received %s\n", str);

CodePudding user response:

You seem to have forgotten that when connected to a pipe stdout is fully buffered.

You need to explicitly flush stdout for the data to actually be written to the pipe. Since the data isn't flushed, there's nothing in the pipe to be read, and the read call blocks.

So after the printf call you need fflush(stdout).

  • Related