Question
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.
Solution
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.