2

I faced a nasty problem:

Suppose I have one program, let's name it HelloProgram which code is very simple:

void print_bullshit() {
 int i;
 for (i = 0; i < 10; ++i) {
  printf("hello!");
  sleep(3);
 }
 printf("bye!");
}

And I have another program, let's name it Redirector, which code is a bit complicated:

#define READ_END 0
#define WRITE_END 1

int pipe_fd[2];
void child_proc(const char* prg_name) {
 close(pipe_fd[READ_END]);

 dup2(pipe_fd[WRITE_END], STDOUT_FILENO));
 execl("/bin/sh", "sh", "-c", prg_name, NULL);
 //error
 exit(1);
}

void parent_proc() {
 close(pipe_fd[WRITE_END]);
 char buffer[256];
 while (read(pipe_fd[READ_END], buffer, sizeof(buffer)) > 0) {
  printf(buffer);
 }

 wait(NULL);
}

int main(int argc, const char* argv[]) {
 pipe(pipe_fd);
 pid_t chpid = fork();
 if (chpid != 0) {
  parent_proc();
 } else {
  child_proc(argv[1]);
 }

 return 0;
}

Some error-checks are not stated there, that's to make code more simple. I still can't understand this thing:

When Redirector is used with HelloProgram to redirect it's output, all the 'Hello' text is given to the console screen only after 3 * 10 (== number of iterations) == 30 seconds,

what the hell is that? I supposed it would be some kind of parallel, so I got each 'Hello' string displayed on the console after every 3 second.

Help me, please.

inaumov17
  • 1,329
  • 11
  • 18
  • 1
    If you want output to appear, finish the string with a newline. Otherwise, it is held pending until you either `fflush()` or `fclose()` the stream, or you print the newline. After using `dup2()` to create standard output, you need to close the pipe file descriptor, too. – Jonathan Leffler Apr 12 '14 at 22:38

1 Answers1

3

If you want the output in HelloProgram to appear timely, you have to either include a newline at the end of each printf(), or use fflush() to force it out. If the output from HelloProgram is going to a terminal, newlines are sufficient; if it is going to a pipe, you need fflush().

Hence:

void print_bullshit(void)
{
    int i;
    for (i = 0; i < 10; ++i)
    { 
        printf("hello!\n");
        fflush(stdout);
        sleep(3);
    }
    printf("bye!\n");
    fflush(stdout);
}

This will send material to its standard output as timely as possible.

In your other code, you have:

void child_proc(const char* prg_name)
{
    close(pipe_fd[READ_END]);
    dup2(pipe_fd[WRITE_END], STDOUT_FILENO));
    execl("/bin/sh", "sh", "-c", prg_name, NULL);
    //error
    exit(1);
}

You need, in general, to add:

close(pipe_fd[WRITE_END]);

after the dup2() call. In this case, it may not matter, but in general, you don't want it left open. Arguably, the code in parent_proc() should close the read end of the pipe when it has read EOF. However, in this program, that won't matter either.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278