Salamandar
Salamandar

Reputation: 598

dup2 : write() redirected but not fprintf() or puts()

I'm trying to read the STDOUT of a child process.

Here is the fork function (yes, c++).

bool ForkAvecBus::start() {
    child_pid = fork();

    if(child_pid == -1)
        return true;

    if(child_pid == 0) {
        /* Child process closes up input side of pipe */
        close(child_stdin[WRITE]);
        dup2 (child_stdin[READ], STDIN_FILENO);

        close(child_stdout[READ]);
        dup2 (child_stdout[WRITE], STDOUT_FILENO);
        close(child_stdout[WRITE]);

        execl("/bin/sh", "/bin/sh", "-c", ExecName.c_str(), NULL);
        exit(0);

    } else {
        /* Parent process closes up output side of pipe */
        close(child_stdin[READ]);
        close(child_stdout[WRITE]);

        signal(SIGTERM,exit_on_parent_quit);
    }
}

Here is the (simple) test in the child process :

int main() {
    fprintf(stdout, "fromFprintf\n", 12);
    puts("auieauie");
    write(STDOUT_FILENO, "fromWrite", 9);
}

And here is the method for reading :

void ForkAvecBus::readFromChild() {
    FILE* fp = fdopen(child_stdout[READ], "r");
    // Tests
    int bytes_read = -1;
    char readbuffer[1000];
    while (1) {
        //char c=getc(fp);
        //std::cout << "From child: <<" << c << ">>" << std::endl;

        bytes_read = read(child_stdout[READ], readbuffer, 999);
        if (bytes_read <= 0)
            break;
        readbuffer[bytes_read] = '\0';
        std::cout << "From child: <<" << readbuffer << ">>" << std::endl;
    }
}

As you can see I tried getc() too. And all I get is :

From child: <<fromWrite>>

Why fprintf (and printf) and puts are not redirected ?

Upvotes: 3

Views: 304

Answers (1)

gdlmx
gdlmx

Reputation: 6789

The behavior you observe here is likely due to buffer. Since write(STDOUT_FILENO,...) bypass the run-time buffer so it directly reaches the pipe. The other two are buffered inside the runtime.

The different between puts, fprintf(stdout,...) and write(STDOUT_FILENO,...) is explained in this post: The difference between stdout and STDOUT_FILENO in LINUX C

Simply call fflush at the end of your child program.

To test the theory:

#include<cstdio>
#include<unistd.h>
int main() {
  fprintf(stdout, "fromFprintf\n", 12);
  puts("auieauie");
  write(STDOUT_FILENO, "fromWrite", 9);
  return 0;
}

The program prints:

fromWritefromFprintf
auieauie

See the order is not what you would expect. My suggestion is don't miss up STDOUT_FILENO and stdout in your program. Stick to one of them and remember to call fflush.

Upvotes: 2

Related Questions