On 9/25/25 02:44, Daniel P. Berrangé wrote:
This addresses two key gotchas with the logging APIs:

  * Safely outputting a single line of text using
    multiple qemu_log() calls requires use of the
    qemu_log_trylock/unlock functions to avoid
    interleaving between threads

  * Directly outputting to the FILE object returned
    by qemu_log_trylock() must be discouraged because
    it prevents the inclusion of configured log message
    prefixes.

I disagree with this point.


Reported-by: Markus Armbruster <arm...@redhat.com>
Signed-off-by: Daniel P. Berrangé <berra...@redhat.com>
---
  include/qemu/log-for-trace.h | 35 ++++++++++++++++++++++++++++++++++-
  include/qemu/log.h           | 26 ++++++++++++++++++++++++++
  rust/util/src/log.rs         |  7 +++++++
  3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/include/qemu/log-for-trace.h b/include/qemu/log-for-trace.h
index d47c9cd446..4e05b2e26f 100644
--- a/include/qemu/log-for-trace.h
+++ b/include/qemu/log-for-trace.h
@@ -29,7 +29,40 @@ static inline bool qemu_loglevel_mask(int mask)
      return (qemu_loglevel & mask) != 0;
  }
-/* main logging function */
+/**
+ * qemu_log: report a log message
+ * @fmt: the format string for the message
+ * @...: the format string arguments
+ *
+ * This will emit a log message to the current output stream.
+ *
+ * The @fmt string should normally represent a complete line
+ * of text, ending with a newline character.
+ *
+ * If intending to call this function multiple times to
+ * incrementally construct a line of text, locking must
+ * be used to ensure that output from different threads
+ * is not interleaved.
+ *
+ * This is achieved by calling qemu_log_trylock() before
+ * starting the log line; calling qemu_log() multiple
+ * times with the last call having a newline at the end
+ * of @fmt; finishing with a call to qemu_log_unlock().
+ *
+ * The FILE object returned by qemu_log_trylock() does
+ * not need to be used for outputting text directly,
+ * it is merely used to associate the lock.
+ *
+ *    FILE *f = qemu_log_trylock()
+ *
+ *    qemu_log("Something");
+ *    qemu_log("Something");
+ *    qemu_log("Something");
+ *    qemu_log("The end\n");
+ *
+ *    qemu_log_unlock(f);
+ *

And I really don't like documenting this as the "right way".

I believe that qemu_log *should* be used only for single-line output, all in one piece. Larger blocks *should* always use qemu_log_trylock and fprintf. The compiler has optimizations transforming fprintf to fputs and fputc as appropriate.

If we can manage to transform all existing usage of multiple qemu_log, then we can remove the '\n' detection added in patch 8.

As far as adding the new prefixes... perhaps we should have something like

FILE *qemu_log_trylock_and_context(bool suppress_context)
{
    FILE *f = qemu_log_trylock();
    if (f && !suppress_context) {
        qmessage_context_print(f);
    }
    return f;
}

where qemu_log would do

    f = qemu_log_trylock_and_context(incomplete);


r~

Reply via email to