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)
.