I'm using the ncurses library in a C project, and encountered a problem with the use of printf()/puts() after curses was initialized and de-initialized. Here's a simplified illustration:
initscr();
endwin();
puts("first");
usleep(1e6);
puts("second");
Both first and second will appear on the screen only after the containing executable exits (after a little over one second), instead of printing first first, and then, a second later, second. ncurses seems to be buffering stdout somehow and only flushing it on exit. fflush(stdout) seems to solve the problem:
initscr();
endwin();
puts("First.");
fflush(stdout);
usleep(1e6);
puts("Second");
When stdout is manually flushed, output is displayed as expected (with a second gap). If I were to add more puts() statements afterwards with usleep()s in between, though, I'd need to repeat the calls to fflush(stdout) after each one, and I'm wondering if there's a better solution that, say, permanently resets the program to pre-curses mode.
ncurses calls setvbuf, putting streams to a full buffered mode. Either specify the environment variable NCURSES_NO_SETBUF to instruct it to not change buffering, or restore the buffer mode by calling setvbuf again, although man 3 setvbuf advises against this:
The setvbuf() function may be used at any time, but may have peculiar side effects (such as discarding input or flushing output) if the stream is ``active''. Portable applications should call it only once on any given stream, and before any I/O is performed.
Here is how to restore stdout to line-buffering and stderr to no buffering again:
#include <stdio.h>
#include <unistd.h>
#include <ncurses.h>
int main() {
initscr();
endwin();
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
puts("First.");
usleep(1e6);
puts("Second");
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With