Use manual line buffering for stdout/stderr.

This is needed for Windows where line buffering is not supported.
This commit is contained in:
Andrea Mazzoleni 2015-03-23 22:57:36 +01:00
parent 20a565a8c1
commit 21ce043725
6 changed files with 34 additions and 29 deletions

View file

@ -223,11 +223,6 @@ void os_init(int opt)
exedir_init();
/* set stdout and stderr as "line buffered" */
/* this ensures that messages are mixed correctly */
setvbuf(stdout, 0, _IOLBF, BUFSIZ);
setvbuf(stderr, 0, _IOLBF, BUFSIZ);
last_error = 0;
}

View file

@ -136,13 +136,13 @@ void parity_overflow(struct snapraid_state* state, data_off_t size)
if (file->blockmax > 0) {
if (file->blockvec[file->blockmax - 1].parity_pos >= blockalloc) {
msg_tag("outofparity:%s:%s\n", disk->name, esc(file->sub));
msg_flush();
if (first) {
first = 0;
msg_warning("\nYour data requires more parity than the available space.\n");
msg_warning("Please move the files 'outofparity' to another data disk:\n");
}
msg_warning("outofparity %s%s\n", disk->dir, file->sub);
msg_flush();
}
}
}

View file

@ -930,7 +930,6 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
}
if (state->filter_hidden)
msg_tag("filter:nohidden:\n");
msg_flush();
}
@ -4633,6 +4632,7 @@ void state_progress_end(struct snapraid_state* state, block_off_t countpos, bloc
if (elapsed >= 60)
msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60));
msg_bar("\n");
msg_flush();
}
}
@ -4642,8 +4642,10 @@ void state_progress_stop(struct snapraid_state* state)
now = time(0);
if (!state->opt.gui)
if (!state->opt.gui) {
msg_bar("\n");
msg_flush();
}
state->progress_interruption = now;
}
@ -4759,7 +4761,7 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
if (out_eta)
msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60);
msg_bar("%s\r", PROGRESS_CLEAR);
fflush(stdout);
msg_flush();
}
/* store the new measure */

View file

@ -24,13 +24,22 @@
int msg_level = 0;
/*
* Note that in the following functions we always flush both
* stdout and stderr, because we want to ensure that they mixes
* well when redirected to files
*
* The buffering is similar at the "line buffered" one, that
* is not available on Windows, so we emulate it in this way.
*
* For stdlog the flush is only limited.
* To ensure flushing the caller should use msg_flush().
*/
void msg_error(const char* format, ...)
{
va_list ap;
/* first output the same message to stdlog and flush it */
/* to avoid to mix messages in case streams are redirected */
/* to the same file */
if (stdlog) {
va_start(ap, format);
fprintf(stdlog, "msg:error: ");
@ -41,6 +50,7 @@ void msg_error(const char* format, ...)
va_start(ap, format);
vfprintf(stderr, format, ap);
fflush(stderr);
va_end(ap);
}
@ -52,10 +62,12 @@ void msg_warning(const char* format, ...)
va_start(ap, format);
fprintf(stdlog, "msg:warning: ");
vfprintf(stdlog, format, ap);
fflush(stdlog);
va_start(ap, format);
} else {
va_start(ap, format);
vfprintf(stderr, format, ap);
fflush(stderr);
va_start(ap, format);
}
}
@ -75,20 +87,18 @@ void msg_status(const char* format, ...)
{
va_list ap;
/* first output the same message to stdlog and flush it */
/* to avoid to mix messages in case streams are redirected */
/* to the same file */
if (stdlog) {
va_start(ap, format);
fprintf(stdlog, "msg:status: ");
vfprintf(stdlog, format, ap);
va_end(ap);
fflush(stdlog);
va_end(ap);
}
if (msg_level >= MSG_STATUS) {
va_start(ap, format);
vfprintf(stdout, format, ap);
fflush(stdout);
va_end(ap);
}
}
@ -103,6 +113,7 @@ void msg_info(const char* format, ...)
if (msg_level >= MSG_INFO) {
va_start(ap, format);
vfprintf(stdout, format, ap);
fflush(stdout);
va_end(ap);
}
}
@ -111,20 +122,18 @@ void msg_progress(const char* format, ...)
{
va_list ap;
/* first output the same message to stdlog and flush it */
/* to avoid to mix messages in case streams are redirected */
/* to the same file */
if (stdlog) {
va_start(ap, format);
fprintf(stdlog, "msg:progress: ");
vfprintf(stdlog, format, ap);
va_end(ap);
fflush(stdlog);
va_end(ap);
}
if (msg_level >= MSG_PROGRESS) {
va_start(ap, format);
vfprintf(stdout, format, ap);
fflush(stdout);
va_end(ap);
}
}
@ -135,6 +144,7 @@ void msg_bar(const char* format, ...)
/* don't output in stdlog as these messages */
/* are intended for screen only */
/* also don't flush stdout as they are intended to be partial messages */
if (msg_level >= MSG_BAR) {
va_start(ap, format);
@ -147,20 +157,18 @@ void msg_verbose(const char* format, ...)
{
va_list ap;
/* first output the same message to stdlog and flush it */
/* to avoid to mix messages in case streams are redirected */
/* to the same file */
if (stdlog) {
va_start(ap, format);
fprintf(stdlog, "msg:verbose: ");
vfprintf(stdlog, format, ap);
va_end(ap);
fflush(stdlog);
va_end(ap);
}
if (msg_level >= MSG_VERBOSE) {
va_start(ap, format);
vfprintf(stdout, format, ap);
fflush(stdout);
va_end(ap);
}
}
@ -170,6 +178,7 @@ void msg_flush(void)
if (stdlog)
fflush(stdlog);
fflush(stdout);
fflush(stderr);
}
/**

View file

@ -50,6 +50,8 @@ void msg_warning(const char* format, ...) __attribute__((format(attribute_printf
* These messages neves go on the screen, but only in the log file if specified.
*
* Note that this function, allows not \n terminated strings.
*
* These messages are buffered. Use msg_flush() to flush them.
*/
void msg_tag(const char* format, ...) __attribute__((format(attribute_printf, 1, 2)));
@ -106,6 +108,8 @@ void msg_progress(const char* format, ...) __attribute__((format(attribute_print
* Message that show the percentage of the progress.
*
* These messages never go in the log file.
*
* These messages are buffered. Use msg_flush() to flush them.
*/
void msg_bar(const char* format, ...) __attribute__((format(attribute_printf, 1, 2)));

View file

@ -958,11 +958,6 @@ int devquery(tommy_list* high, tommy_list* low, int operation)
void os_init(int opt)
{
(void)opt;
/* set stdout and stderr as "line buffered" */
/* this ensures that messages are mixed correctly */
setvbuf(stdout, 0, _IOLBF, BUFSIZ);
setvbuf(stderr, 0, _IOLBF, BUFSIZ);
}
void os_done(void)