virsh: properly interleave shared stdout and stderr

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 commit is contained in:
Eric Blake 2011-08-19 09:20:35 -06:00
parent d89dd42d51
commit baac9c37d7
2 changed files with 9 additions and 4 deletions

View File

@ -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

View File

@ -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);
}