As per the document, which says that[emphasis mine]:
FILE *popen(const char *command, const char *type);
Note that output
popen()
streams are block buffered by default.
I hope to see the output of the command executed by popen
as soon as possible.So I change the buffering type of the file stream returned by popen
to line buffered. As per the document, setvbuf
seems work for this goal. But after I did a simple test on Ubuntu16.4
, setvbuf
does not work indeed.
Here is the code snippet which I used to do the said test:
#include <stdio.h>
#include <thread>
#include <chrono>
#include <iostream>
#include <array>
int main(void)
{
std::array<char, 1024> buffer;
buffer.fill('\0');
FILE* file = popen("bash -c \"for i in 1 2 3 4 5;do echo -e -n 'thanks a lot\n'; sleep 1; done\" ", "r");
if(nullptr != file)
{
std::cout << setvbuf(file, NULL, _IOLBF, 0) << std::endl;
while(fread(buffer.data(), 1, buffer.size(), file)>0)
{
std::cout << buffer.data() << std::endl;
buffer.fill('\0');
}
}
return 0;
}
Here is the output of the code snippet above:
0
//about five seconds later!
thanks a lot
thanks a lot
thanks a lot
thanks a lot
thanks a lot
As per the document, which says that:
The function setvbuf() returns 0 on success.
As per the output above, setvbuf(file, NULL, _IOLBF, 0)
has successfully set the buffing type of file
returned by popen
to line buffered.But the output of the aforementioned code snippet indicates it still uses the default block buffered.
I am really conscious why it works this way.
I did an extra test about setvbuf
to try to make it clear.
As per the document, which says that:
If a stream refers to a terminal (as stdout normally does) it is line buffered. The standard error stream stderr is always unbuffered by default.
So I modify the buffing type of stdout
by setvbuf(stdout, NULL, _IOFBF, 0);
.
Here is the full code snippet:
#include <stdio.h>
#include <thread>
#include <chrono>
int
main(void)
{
char buf[BUFSIZ];
setvbuf(stdout, NULL, _IOFBF, 0);
for(int i=0; i<10; i++)
{
printf("Hello, world!\n");
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
return 0;
}
Here is the ouput:
//about ten seconds later
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
The output is printed out to the terminal after about ten seconds, which is in the expectation.