Without this patch, invoking 'virsh>file 2>&1'
results in
error messages appearing before normal output, even if they
occurred later in time than the normal output (since stderr
is unbuffered, but stdout waits until a full buffer).
* tools/virsh.c (print_job_progress, vshError): Flush between
stream transitions.
* tests/undefine: Test it.
---
This fixes the bug I mentioned here:
https://www.redhat.com/archives/libvir-list/2011-August/msg00891.html
tests/undefine | 5 +----
tools/virsh.c | 8 ++++++++
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/tests/undefine b/tests/undefine
index 6c821ad..22d6c14 100755
--- a/tests/undefine
+++ b/tests/undefine
@@ -58,17 +58,14 @@ compare exp out || fail=1
# Succeed, now: first shut down, then undefine, both via name.
$abs_top_builddir/tools/virsh -q -c test:///default \
- 'shutdown test; undefine test; dominfo test'> out 2> err
+ 'shutdown test; undefine test; dominfo test'> out 2>&1
test $? = 1 || fail=1
cat<<\EOF> expout || fail=1
Domain test is being shutdown
Domain test has been undefined
-EOF
-cat<<\EOF> experr || fail=1
error: failed to get domain 'test'
error: Domain not found
EOF
compare expout out || fail=1
-compare experr err || fail=1
(exit $fail); exit $fail
diff --git a/tools/virsh.c b/tools/virsh.c
index 1c67150..7d849ec 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -4956,7 +4956,10 @@ print_job_progress(const char *label, unsigned long long
remaining,
}
}
+ /* see comments in vshError about why we must flush */
+ fflush(stdout);
fprintf(stderr, "\r%s: [%3d %%]", label, progress);
+ fflush(stderr);
}
static bool
@@ -14336,6 +14339,10 @@ vshError(vshControl *ctl, const char *format, ...)
va_end(ap);
}
+ /* Most output is to stdout, but if someone ran virsh 2>&1, then
+ * printing to stderr will not interleave correctly with stdout
+ * unless we flush between every transition between streams. */
+ fflush(stdout);
fputs(_("error: "), stderr);
va_start(ap, format);
@@ -14345,6 +14352,7 @@ vshError(vshControl *ctl, const char *format, ...)
va_end(ap);
fprintf(stderr, "%s\n", NULLSTR(str));
+ fflush(stderr);
VIR_FREE(str);
}