qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/20] util: sync error_report & qemu_log output more closely
@ 2025-09-10 18:03 Daniel P. Berrangé
  2025-09-10 18:03 ` [PATCH v3 01/20] include: define constant for early constructor priority Daniel P. Berrangé
                   ` (19 more replies)
  0 siblings, 20 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

This series is a tangent that came out of discussion in

   https://lists.nongnu.org/archive/html/qemu-devel/2025-08/msg00903.html

In thinking about adding thread info to error_report, I
came to realize we should likely make qemu_log behave
consistently with error_report & friends. We already
honour '-msg timestamp=on', but don't honour 'guest-name=on'
and also don't include the binary name.

As an example of the current state, consider mixing error and
log output today:

- Default context:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish \
                       -d 'trace:qcrypto*'
  qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55ac6d97f700 dir=fish
  qcrypto_tls_creds_get_path TLS creds path creds=0x55ac6d97f700 filename=ca-cert.pem path=<none>
  qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

- Full context:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish \
                       -d 'trace:qcrypto*' \
                       -msg guest-name=on,timestamp=on \
                       -name "fish food"
  2025-08-19T20:14:16.791413Z qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55e9a3458d10 dir=fish
  2025-08-19T20:14:16.791429Z qcrypto_tls_creds_get_path TLS creds path creds=0x55e9a3458d10 filename=ca-cert.pem path=<none>
  2025-08-19T20:14:16.791433Z fish food qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

And after this series is complete:

- Default context:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish \
                      -d 'trace:qcrypto*'
  qemu-system-x86_64(1184284:main): qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55a24ad5cb30 dir=fish
  qemu-system-x86_64(1184284:main): qcrypto_tls_creds_get_path TLS creds path creds=0x55a24ad5cb30 filename=ca-cert.pem path=<none>
  qemu-system-x86_64(1184284:main): Unable to access credentials fish/ca-cert.pem: No such file or directory

- Full context:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish \
                      -d 'trace:qcrypto*' \
                      -msg guest-name=on,timestamp=on \
                      -name "fish food"
  2025-08-19T20:12:50.211823Z [fish food] qemu-system-x86_64(1168876:main): qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x5582183d8760 dir=fish
  2025-08-19T20:12:50.211842Z [fish food] qemu-system-x86_64(1168876:main): qcrypto_tls_creds_get_path TLS creds path creds=0x5582183d8760 filename=ca-cert.pem
+path=<none>
  2025-08-19T20:12:50.211846Z [fish food] qemu-system-x86_64(1168876:main): Unable to access credentials fish/ca-cert.pem: No such file or directory

The main things to note:

 * error_report/warn_report/qemu_log share the same
   output format and -msg applies to both

 * -msg debug-threads=on is now unconditionally enabled
   and thus the param is deprecated & ignored

 * Thread ID and name are unconditionally enabled

 * Guest name is surrounded in [...] brackets

 * The default output lines are typically 15 chars
   wider given that we always include the thread
   ID + name now

 * This takes the liberty of assigning the new file
   to the existing error-report.c maintainer (Markus)
   Since splitting it off into message.c instead of
   putting it all in error-report.c felt slightly
   nicer.

One thing I didn't tackle is making the location
info get reported for qemu_log. This is used to
give context for error messages when parsing some
CLI args, and could be interesting for log messages
associated with those same CLI args.

Changes in v3:

 - Stop formatting a string in qmessage_context, instead
   output directly to a "FILE *" stream
 - Fix pre-existing bug interleaving qemu_log and
   vreport when the trace 'log' backend has mutex probes
   enabled
 - Don't skip error prefixes on stderr when vreport
   is called from QMP context.
 - Remove little used error_[v]printf_unless_qmp funcs

Changes in v2:

 - Re-use existing qemu_get_thread_id rather than
   re-inventing it as qemu_thread_get_id.
 - Expose qemu_thread_set_name and use it from all
   locations needing to set thread names
 - Fix qemu_log() to skip context prefix when
   emitting a log message in fragments across
   multiple calls
 - Skip allocating memory for empty context messages
 - Fix leak in win32 impl of qemu_thread_get_name
 - Use g_strlcpy where possible

Daniel P. Berrangé (20):
  include: define constant for early constructor priority
  monitor: initialize global data from a constructor
  system: unconditionally enable thread naming
  util: expose qemu_thread_set_name
  audio: make jackaudio use qemu_thread_set_name
  util: set the name for the 'main' thread
  util: add API to fetch the current thread name
  log: avoid repeated prefix on incremental qemu_log calls
  ui/vnc: remove use of error_printf_unless_qmp()
  monitor: remove redundant error_[v]printf_unless_qmp
  monitor: move error_vprintf() back to error-report.c
  monitor: introduce monitor_cur_hmp() function
  util: don't skip error prefixes when QMP is active
  util: fix interleaving of error & trace output
  util: introduce common helper for error-report & log code
  util: convert error-report & log to message API for timestamp
  util: add support for formatting a workload name in messages
  util: add support for formatting a program name in messages
  util: add support for formatting thread info in messages
  util: add brackets around guest name in message context

 MAINTAINERS                          |  2 +
 audio/jackaudio.c                    | 30 ++++++++--
 docs/about/deprecated.rst            |  7 +++
 include/monitor/monitor.h            |  4 +-
 include/qemu/compiler.h              |  8 +++
 include/qemu/error-report.h          |  4 --
 include/qemu/message.h               | 40 +++++++++++++
 include/qemu/thread.h                |  3 +-
 meson.build                          | 21 +++++++
 monitor/monitor.c                    | 65 +++++++-------------
 storage-daemon/qemu-storage-daemon.c |  6 ++
 stubs/error-printf.c                 |  5 --
 stubs/monitor-core.c                 | 15 +++++
 system/vl.c                          | 30 +++++++---
 tests/qemu-iotests/041               |  2 +-
 tests/qemu-iotests/common.filter     |  2 +-
 tests/unit/test-error-report.c       |  6 +-
 tests/unit/test-util-sockets.c       |  3 +
 ui/vnc.c                             | 14 +++--
 util/error-report.c                  | 89 ++++++++++++++++------------
 util/log.c                           | 28 ++++-----
 util/meson.build                     |  1 +
 util/message.c                       | 47 +++++++++++++++
 util/qemu-thread-posix.c             | 76 +++++++++++++++---------
 util/qemu-thread-win32.c             | 82 +++++++++++++++++--------
 25 files changed, 404 insertions(+), 186 deletions(-)
 create mode 100644 include/qemu/message.h
 create mode 100644 util/message.c

-- 
2.50.1



^ permalink raw reply	[flat|nested] 84+ messages in thread

* [PATCH v3 01/20] include: define constant for early constructor priority
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-10 18:03 ` [PATCH v3 02/20] monitor: initialize global data from a constructor Daniel P. Berrangé
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

Functions marked with __attribute__((__constructor__)) will be
invoked in linker order. In theory this is well defined, but
in practice, it is hard to determine what this order will be
with the layers of indirection through meson, ninja and the
static libraries QEMU builds.

Notably, the order currently appears different between Linux
and Windows (as tested with Wine on Linux). This can cause
problems when certain QEMU constructors have a dependancy on
other QEMU constructors.

To address this define a QEMU_CONSTRUCTOR_EARLY constant which
provides a priority value that will run before other default
constructors. This is to be used for QEMU constructors that
are themselves self-contained, but may be relied upon by other
constructors.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/compiler.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 1c2b673c05..4c49f52eb0 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -194,6 +194,14 @@
 # define QEMU_USED
 #endif
 
+/*
+ * A priority for __attribute__((constructor(...))) that
+ * will run earlier than the default constructors. Must
+ * only be used for functions that have no dependency
+ * on global initialization of other QEMU subsystems.
+ */
+#define QEMU_CONSTRUCTOR_EARLY 101
+
 /*
  * Disable -ftrivial-auto-var-init on a local variable.
  *
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 02/20] monitor: initialize global data from a constructor
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
  2025-09-10 18:03 ` [PATCH v3 01/20] include: define constant for early constructor priority Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-17 14:07   ` Markus Armbruster
  2025-09-10 18:03 ` [PATCH v3 03/20] system: unconditionally enable thread naming Daniel P. Berrangé
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

Some monitor functions, most notably, monitor_cur() rely on global
data being initialized by 'monitor_init_globals()'. The latter is
called relatively late in startup. If code triggers error_report()
before monitor_init_globals() is called, QEMU will abort when
accessing the uninitialized monitor mutex.

The critical monitor global data must be initialized from a
constructor function, to improve the guarantee that it is done
before any possible calls to monitor_cur(). Not only that, but
the constructor must be marked to run before the default
constructor in case any of them trigger error reporting.

Note in particular that the RCU constructor will spawn a background
thread so we might even have non-constructor QEMU code running
concurrently with other constructors.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 monitor/monitor.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/monitor/monitor.c b/monitor/monitor.c
index c5a5d30877..da54e1b1ce 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -704,18 +704,22 @@ void monitor_cleanup(void)
     }
 }
 
-static void monitor_qapi_event_init(void)
+/*
+ * Initialize static vars that have no deps on external
+ * module initialization, and are required for external
+ * functions to call things like monitor_cur()
+ */
+static void __attribute__((__constructor__(QEMU_CONSTRUCTOR_EARLY)))
+monitor_init_static(void)
 {
+    qemu_mutex_init(&monitor_lock);
+    coroutine_mon = g_hash_table_new(NULL, NULL);
     monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash,
                                                 qapi_event_throttle_equal);
 }
 
 void monitor_init_globals(void)
 {
-    monitor_qapi_event_init();
-    qemu_mutex_init(&monitor_lock);
-    coroutine_mon = g_hash_table_new(NULL, NULL);
-
     /*
      * The dispatcher BH must run in the main loop thread, since we
      * have commands assuming that context.  It would be nice to get
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 03/20] system: unconditionally enable thread naming
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
  2025-09-10 18:03 ` [PATCH v3 01/20] include: define constant for early constructor priority Daniel P. Berrangé
  2025-09-10 18:03 ` [PATCH v3 02/20] monitor: initialize global data from a constructor Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 12:18   ` Ján Tomko
  2025-09-19  8:20   ` Markus Armbruster
  2025-09-10 18:03 ` [PATCH v3 04/20] util: expose qemu_thread_set_name Daniel P. Berrangé
                   ` (16 subsequent siblings)
  19 siblings, 2 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

When thread naming was introduced years ago, it was disabled by
default and put behind a command line flag:

  commit 8f480de0c91a18d550721f8d9af969ebfbda0793
  Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
  Date:   Thu Jan 30 10:20:31 2014 +0000

    Add 'debug-threads' suboption to --name

This was done based on a concern that something might depend
on the historical thread naming. Thread names, however, were
never promised to be part of QEMU's public API. The defaults
will vary across platforms, so no assumptions should ever be
made about naming.

An opt-in behaviour is also unfortunately incompatible with
RCU which creates its thread from an constructor function
which is run before command line args are parsed. Thus the
RCU thread lacks any name.

libvirt has unconditionally enabled debug-threads=yes on all
VMs it creates for 10 years. Interestingly this DID expose a
bug in libvirt, as it parsed /proc/$PID/stat and could not
cope with a space in the thread name. This was a latent
pre-existing bug in libvirt though, and not a part of QEMU's
API.

Having thread names always available, will allow thread names
to be included in error reports and log messags QEMU prints
by default, which will improve ability to triage QEMU bugs.

Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 docs/about/deprecated.rst |  7 +++++++
 include/qemu/thread.h     |  1 -
 system/vl.c               | 11 ++++++-----
 util/qemu-thread-posix.c  | 18 +-----------------
 util/qemu-thread-win32.c  | 27 ++++++---------------------
 5 files changed, 20 insertions(+), 44 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index b2420732e1..7187ea15fa 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -81,6 +81,13 @@ kernel since 2001. None of the board types QEMU supports need
 ``param_struct`` support, so this option has been deprecated and will
 be removed in a future QEMU version.
 
+``debug-threads`` option for ``-name``
+''''''''''''''''''''''''''''''''''''''
+
+Thread ``debug-threads`` option for the ``-name`` argument is now
+ignored. Thread naming is unconditionally enabled for all platforms
+where it is supported.
+
 QEMU Machine Protocol (QMP) commands
 ------------------------------------
 
diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index f0302ed01f..3a286bb3ef 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -215,7 +215,6 @@ void *qemu_thread_join(QemuThread *thread);
 void qemu_thread_get_self(QemuThread *thread);
 bool qemu_thread_is_self(QemuThread *thread);
 G_NORETURN void qemu_thread_exit(void *retval);
-void qemu_thread_naming(bool enable);
 
 struct Notifier;
 /**
diff --git a/system/vl.c b/system/vl.c
index 3b7057e6c6..a64fd90d4a 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -403,9 +403,7 @@ static QemuOptsList qemu_name_opts = {
         }, {
             .name = "debug-threads",
             .type = QEMU_OPT_BOOL,
-            .help = "When enabled, name the individual threads; defaults off.\n"
-                    "NOTE: The thread names are for debugging and not a\n"
-                    "stable API.",
+            .help = "DEPRECATED: thread names are always set where supported",
         },
         { /* End of list */ }
     },
@@ -554,9 +552,12 @@ static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
 {
     const char *proc_name;
 
-    if (qemu_opt_get(opts, "debug-threads")) {
-        qemu_thread_naming(qemu_opt_get_bool(opts, "debug-threads", false));
+    if (qemu_opt_get(opts, "debug-threads") &&
+        !qemu_opt_get_bool(opts, "debug-threads", false)) {
+        fprintf(stderr, "Ignoring deprecated 'debug-threads=no' option, " \
+                "thread naming is unconditionally enabled\n");
     }
+
     qemu_name = qemu_opt_get(opts, "guest");
 
     proc_name = qemu_opt_get(opts, "process");
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index ba725444ba..7c985b5d38 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -22,22 +22,6 @@
 #include <pthread_np.h>
 #endif
 
-static bool name_threads;
-
-void qemu_thread_naming(bool enable)
-{
-    name_threads = enable;
-
-#if !defined CONFIG_PTHREAD_SETNAME_NP_W_TID && \
-    !defined CONFIG_PTHREAD_SETNAME_NP_WO_TID && \
-    !defined CONFIG_PTHREAD_SET_NAME_NP
-    /* This is a debugging option, not fatal */
-    if (enable) {
-        fprintf(stderr, "qemu: thread naming not supported on this host\n");
-    }
-#endif
-}
-
 static void error_exit(int err, const char *msg)
 {
     fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
@@ -361,7 +345,7 @@ static void *qemu_thread_start(void *args)
     /* Attempt to set the threads name; note that this is for debug, so
      * we're not going to fail if we can't set it.
      */
-    if (name_threads && qemu_thread_args->name) {
+    if (qemu_thread_args->name) {
 # if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
         pthread_setname_np(pthread_self(), qemu_thread_args->name);
 # elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index ca2e0b512e..9595a5b090 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -17,8 +17,6 @@
 #include "qemu-thread-common.h"
 #include <process.h>
 
-static bool name_threads;
-
 typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
                                                  PCWSTR lpThreadDescription);
 static pSetThreadDescription SetThreadDescriptionFunc;
@@ -44,16 +42,6 @@ static bool load_set_thread_description(void)
     return !!SetThreadDescriptionFunc;
 }
 
-void qemu_thread_naming(bool enable)
-{
-    name_threads = enable;
-
-    if (enable && !load_set_thread_description()) {
-        fprintf(stderr, "qemu: thread naming not supported on this host\n");
-        name_threads = false;
-    }
-}
-
 static void error_exit(int err, const char *msg)
 {
     char *pstr;
@@ -328,23 +316,20 @@ void *qemu_thread_join(QemuThread *thread)
     return ret;
 }
 
-static bool set_thread_description(HANDLE h, const char *name)
+static void set_thread_description(HANDLE h, const char *name)
 {
-    HRESULT hr;
     g_autofree wchar_t *namew = NULL;
 
     if (!load_set_thread_description()) {
-        return false;
+        return;
     }
 
     namew = g_utf8_to_utf16(name, -1, NULL, NULL, NULL);
     if (!namew) {
-        return false;
+        return;
     }
 
-    hr = SetThreadDescriptionFunc(h, namew);
-
-    return SUCCEEDED(hr);
+    SetThreadDescriptionFunc(h, namew);
 }
 
 void qemu_thread_create(QemuThread *thread, const char *name,
@@ -370,8 +355,8 @@ void qemu_thread_create(QemuThread *thread, const char *name,
     if (!hThread) {
         error_exit(GetLastError(), __func__);
     }
-    if (name_threads && name && !set_thread_description(hThread, name)) {
-        fprintf(stderr, "qemu: failed to set thread description: %s\n", name);
+    if (name) {
+        set_thread_description(hThread, name);
     }
     CloseHandle(hThread);
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 04/20] util: expose qemu_thread_set_name
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (2 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 03/20] system: unconditionally enable thread naming Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-19  8:39   ` Markus Armbruster
  2025-09-10 18:03 ` [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name Daniel P. Berrangé
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The ability to set the thread name needs to be used in a number
of places, so expose the current impls as public methods.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/thread.h    |  1 +
 util/qemu-thread-posix.c | 30 ++++++++++++++++++------------
 util/qemu-thread-win32.c |  6 +++---
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index 3a286bb3ef..27b888ab0a 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -215,6 +215,7 @@ void *qemu_thread_join(QemuThread *thread);
 void qemu_thread_get_self(QemuThread *thread);
 bool qemu_thread_is_self(QemuThread *thread);
 G_NORETURN void qemu_thread_exit(void *retval);
+void qemu_thread_set_name(const char *name);
 
 struct Notifier;
 /**
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index 7c985b5d38..ddaa1de4dd 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -329,6 +329,21 @@ static void qemu_thread_atexit_notify(void *arg)
     notifier_list_notify(&thread_exit, NULL);
 }
 
+void qemu_thread_set_name(const char *name)
+{
+    /*
+     * Attempt to set the threads name; note that this is for debug, so
+     * we're not going to fail if we can't set it.
+     */
+# if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
+    pthread_setname_np(pthread_self(), name);
+# elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
+    pthread_setname_np(name);
+# elif defined(CONFIG_PTHREAD_SET_NAME_NP)
+    pthread_set_name_np(pthread_self(), name);
+# endif
+}
+
 typedef struct {
     void *(*start_routine)(void *);
     void *arg;
@@ -342,20 +357,11 @@ static void *qemu_thread_start(void *args)
     void *arg = qemu_thread_args->arg;
     void *r;
 
-    /* Attempt to set the threads name; note that this is for debug, so
-     * we're not going to fail if we can't set it.
-     */
     if (qemu_thread_args->name) {
-# if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
-        pthread_setname_np(pthread_self(), qemu_thread_args->name);
-# elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
-        pthread_setname_np(qemu_thread_args->name);
-# elif defined(CONFIG_PTHREAD_SET_NAME_NP)
-        pthread_set_name_np(pthread_self(), qemu_thread_args->name);
-# endif
+        qemu_thread_set_name(qemu_thread_args->name);
+        QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
+        g_free(qemu_thread_args->name);
     }
-    QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
-    g_free(qemu_thread_args->name);
     g_free(qemu_thread_args);
 
     /*
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index 9595a5b090..62eaa11026 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -316,7 +316,7 @@ void *qemu_thread_join(QemuThread *thread)
     return ret;
 }
 
-static void set_thread_description(HANDLE h, const char *name)
+void qemu_thread_set_name(const char *name)
 {
     g_autofree wchar_t *namew = NULL;
 
@@ -329,7 +329,7 @@ static void set_thread_description(HANDLE h, const char *name)
         return;
     }
 
-    SetThreadDescriptionFunc(h, namew);
+    SetThreadDescriptionFunc(GetCurrentThread(), namew);
 }
 
 void qemu_thread_create(QemuThread *thread, const char *name,
@@ -356,7 +356,7 @@ void qemu_thread_create(QemuThread *thread, const char *name,
         error_exit(GetLastError(), __func__);
     }
     if (name) {
-        set_thread_description(hThread, name);
+        qemu_thread_set_name(name);
     }
     CloseHandle(hThread);
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (3 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 04/20] util: expose qemu_thread_set_name Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 13:21   ` Christian Schoenebeck
  2025-09-10 18:03 ` [PATCH v3 06/20] util: set the name for the 'main' thread Daniel P. Berrangé
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

This has greater portability than directly call pthread_setname_np,
which is only 1 out of 3 possible functions for pthreads that can
set the name.

The new API requires a trampoline function, since it can only set
the name of the current thread.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 audio/jackaudio.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index 974a3caad3..69dce3f302 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -629,18 +629,36 @@ static void qjack_enable_in(HWVoiceIn *hw, bool enable)
     ji->c.enabled = enable;
 }
 
-#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
+#if !defined(WIN32)
+struct QJackThreadData {
+    void *(*function)(void *);
+    void *arg;
+};
+
+static void *qjack_thread_trampoline(void *targ)
+{
+    struct QJackThreadData *data = targ;
+    void *(*function)(void *) = data->function;
+    void *arg = data->arg;
+
+    g_free(data);
+    qemu_thread_set_name("jack-client");
+
+    return function(arg);
+}
+
 static int qjack_thread_creator(jack_native_thread_t *thread,
     const pthread_attr_t *attr, void *(*function)(void *), void *arg)
 {
-    int ret = pthread_create(thread, attr, function, arg);
+    struct QJackThreadData *data = g_new0(struct QJackThreadData, 1);
+    data->function = function;
+    data->arg = arg;
+    int ret = pthread_create(thread, attr, qjack_thread_trampoline, data);
     if (ret != 0) {
+        g_free(data);
         return ret;
     }
 
-    /* set the name of the thread */
-    pthread_setname_np(*thread, "jack-client");
-
     return ret;
 }
 #endif
@@ -696,7 +714,7 @@ static void register_audio_jack(void)
 {
     qemu_mutex_init(&qjack_shutdown_lock);
     audio_driver_register(&jack_driver);
-#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
+#if !defined(WIN32)
     jack_set_thread_creator(qjack_thread_creator);
 #endif
     jack_set_error_function(qjack_error);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 06/20] util: set the name for the 'main' thread
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (4 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-10 18:03 ` [PATCH v3 07/20] util: add API to fetch the current thread name Daniel P. Berrangé
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The default main thread name is undefined, so use a constructor to
explicitly set it to 'main'. This constructor is marked to run early
as the thread name is intended to be used in error reporting / logs
which may be triggered very early in QEMU execution.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 util/qemu-thread-posix.c | 6 ++++++
 util/qemu-thread-win32.c | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index ddaa1de4dd..275445ed94 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -22,6 +22,12 @@
 #include <pthread_np.h>
 #endif
 
+static void __attribute__((__constructor__(QEMU_CONSTRUCTOR_EARLY)))
+qemu_thread_init(void)
+{
+    qemu_thread_set_name("main");
+}
+
 static void error_exit(int err, const char *msg)
 {
     fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index 62eaa11026..7a734a7a09 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -22,6 +22,12 @@ typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
 static pSetThreadDescription SetThreadDescriptionFunc;
 static HMODULE kernel32_module;
 
+static void __attribute__((__constructor__(QEMU_CONSTRUCTOR_EARLY)))
+qemu_thread_init(void)
+{
+    qemu_thread_set_name("main");
+}
+
 static bool load_set_thread_description(void)
 {
     static gsize _init_once = 0;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 07/20] util: add API to fetch the current thread name
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (5 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 06/20] util: set the name for the 'main' thread Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-19  8:59   ` Markus Armbruster
  2025-09-23 12:12   ` Markus Armbruster
  2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
                   ` (12 subsequent siblings)
  19 siblings, 2 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

This will be used to include the thread name in error reports
in a later patch. It returns a const string stored in a thread
local to avoid memory allocation when it is called repeatedly
in a single thread. This makes the assumption that the thread
name is set at the very start of the thread, which is the case
when using qemu_thread_create.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/thread.h    |  1 +
 meson.build              | 21 +++++++++++++++++
 util/qemu-thread-posix.c | 28 ++++++++++++++++++++++-
 util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
 4 files changed, 94 insertions(+), 5 deletions(-)

diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index 27b888ab0a..98cc5c41ac 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -216,6 +216,7 @@ void qemu_thread_get_self(QemuThread *thread);
 bool qemu_thread_is_self(QemuThread *thread);
 G_NORETURN void qemu_thread_exit(void *retval);
 void qemu_thread_set_name(const char *name);
+const char *qemu_thread_get_name(void);
 
 struct Notifier;
 /**
diff --git a/meson.build b/meson.build
index fa6186db33..6aa673f4b2 100644
--- a/meson.build
+++ b/meson.build
@@ -2920,6 +2920,27 @@ config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(osdep_prefix + '''
     pthread_set_name_np(thread, "QEMU");
     return 0;
   }''', dependencies: threads))
+
+config_host_data.set('CONFIG_PTHREAD_GETNAME_NP', cc.links(osdep_prefix + '''
+  #include <pthread.h>
+
+  int main(void)
+  {
+    char buf[16];
+    pthread_getname_np(pthread_self(), buf, sizeof(buf));
+    return 0;
+  }''', dependencies: threads))
+config_host_data.set('CONFIG_PTHREAD_GET_NAME_NP', cc.links(osdep_prefix + '''
+  #include <pthread.h>
+  #include <pthread_np.h>
+
+  int main(void)
+  {
+    char buf[16];
+    pthread_get_name_np(pthread_self(), buf, sizeof(buf));
+    return 0;
+  }''', dependencies: threads))
+
 config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(osdep_prefix + '''
   #include <pthread.h>
 
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index 275445ed94..fbb94ca97b 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -18,7 +18,7 @@
 #include "qemu/tsan.h"
 #include "qemu/bitmap.h"
 
-#ifdef CONFIG_PTHREAD_SET_NAME_NP
+#if defined(CONFIG_PTHREAD_SET_NAME_NP) || defined(CONFIG_PTHREAD_GET_NAME_NP)
 #include <pthread_np.h>
 #endif
 
@@ -532,3 +532,29 @@ void *qemu_thread_join(QemuThread *thread)
     }
     return ret;
 }
+
+#ifndef PTHREAD_MAX_NAMELEN_NP
+#define PTHREAD_MAX_NAMELEN_NP 16
+#endif
+
+static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP];
+
+const char *qemu_thread_get_name(void)
+{
+    int rv;
+    if (namebuf[0] != '\0') {
+        return namebuf;
+    }
+
+# if defined(CONFIG_PTHREAD_GETNAME_NP)
+    rv = pthread_getname_np(pthread_self(), namebuf, sizeof(namebuf));
+# elif defined(CONFIG_PTHREAD_GET_NAME_NP)
+    rv = pthread_get_name_np(pthread_self(), namebuf, sizeof(namebuf));
+# else
+    rv = -1;
+# endif
+    if (rv != 0) {
+        strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
+    }
+    return namebuf;
+}
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index 7a734a7a09..e3789c20d1 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -19,7 +19,10 @@
 
 typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
                                                  PCWSTR lpThreadDescription);
+typedef HRESULT (WINAPI *pGetThreadDescription) (HANDLE hThread,
+                                                 PWSTR *lpThreadDescription);
 static pSetThreadDescription SetThreadDescriptionFunc;
+static pGetThreadDescription GetThreadDescriptionFunc;
 static HMODULE kernel32_module;
 
 static void __attribute__((__constructor__(QEMU_CONSTRUCTOR_EARLY)))
@@ -28,7 +31,7 @@ qemu_thread_init(void)
     qemu_thread_set_name("main");
 }
 
-static bool load_set_thread_description(void)
+static bool load_thread_description(void)
 {
     static gsize _init_once = 0;
 
@@ -38,14 +41,17 @@ static bool load_set_thread_description(void)
             SetThreadDescriptionFunc =
                 (pSetThreadDescription)GetProcAddress(kernel32_module,
                                                       "SetThreadDescription");
-            if (!SetThreadDescriptionFunc) {
+            GetThreadDescriptionFunc =
+                (pGetThreadDescription)GetProcAddress(kernel32_module,
+                                                      "GetThreadDescription");
+            if (!SetThreadDescriptionFunc || !GetThreadDescriptionFunc) {
                 FreeLibrary(kernel32_module);
             }
         }
         g_once_init_leave(&_init_once, 1);
     }
 
-    return !!SetThreadDescriptionFunc;
+    return !!(SetThreadDescriptionFunc && GetThreadDescriptionFunc);
 }
 
 static void error_exit(int err, const char *msg)
@@ -326,7 +332,7 @@ void qemu_thread_set_name(const char *name)
 {
     g_autofree wchar_t *namew = NULL;
 
-    if (!load_set_thread_description()) {
+    if (!load_thread_description()) {
         return;
     }
 
@@ -412,3 +418,38 @@ bool qemu_thread_is_self(QemuThread *thread)
 {
     return GetCurrentThreadId() == thread->tid;
 }
+
+static __thread char namebuf[64];
+
+const char *qemu_thread_get_name(void)
+{
+    HRESULT hr;
+    wchar_t *namew = NULL;
+    g_autofree char *name = NULL;
+
+    if (namebuf[0] != '\0') {
+        return namebuf;
+    }
+
+    if (!load_thread_description()) {
+        goto error;
+    }
+
+    hr = GetThreadDescriptionFunc(GetCurrentThread(), &namew);
+    if (!SUCCEEDED(hr)) {
+        goto error;
+    }
+
+    name = g_utf16_to_utf8(namew, -1, NULL, NULL, NULL);
+    LocalFree(namew);
+    if (!name) {
+        goto error;
+    }
+
+    g_strlcpy(namebuf, name, G_N_ELEMENTS(namebuf));
+    return namebuf;
+
+ error:
+    strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
+    return namebuf;
+}
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (6 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 07/20] util: add API to fetch the current thread name Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-10 23:20   ` Dr. David Alan Gilbert
                     ` (4 more replies)
  2025-09-10 18:03 ` [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp() Daniel P. Berrangé
                   ` (11 subsequent siblings)
  19 siblings, 5 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

Some code makes multiple qemu_log calls to incrementally emit
a single message. Currently timestamps get prepended to all
qemu_log calls, even those continuing a previous incomplete
message.

This changes the qemu_log so it skips adding a new line prefix,
if the previous qemu_log call did NOT end with a newline.

Reported-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 util/log.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/util/log.c b/util/log.c
index abdcb6b311..2642a55c59 100644
--- a/util/log.c
+++ b/util/log.c
@@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
     }
 }
 
+/*
+ * 'true' if the previous log message lacked a trailing '\n',
+ * and thus the subsequent call must skip any prefix
+ */
+static __thread bool incomplete;
+
 void qemu_log(const char *fmt, ...)
 {
     FILE *f;
@@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
      * was emitted if we are delayed acquiring the
      * mutex
      */
-    if (message_with_timestamp) {
+    if (message_with_timestamp && !incomplete) {
         g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
         timestr = g_date_time_format_iso8601(dt);
     }
@@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
         va_start(ap, fmt);
         vfprintf(f, fmt, ap);
         va_end(ap);
+        incomplete = fmt[strlen(fmt) - 1] != '\n';
         qemu_log_unlock(f);
     }
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp()
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (7 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11  0:08   ` Dr. David Alan Gilbert
                     ` (2 more replies)
  2025-09-10 18:03 ` [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp Daniel P. Berrangé
                   ` (10 subsequent siblings)
  19 siblings, 3 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The error_printf_unless_qmp() will print to the monitor if the current
one is HMP, if it is QMP nothing will be printed, otherwise stderr
will be used.

This scenario is easily handled by checking !monitor_cur_is_qmp() and
then calling the error_printf() function.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 ui/vnc.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 68ca4a68e7..439d586358 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3530,8 +3530,10 @@ int vnc_display_password(const char *id, const char *password)
         return -EINVAL;
     }
     if (vd->auth == VNC_AUTH_NONE) {
-        error_printf_unless_qmp("If you want use passwords please enable "
-                                "password auth using '-vnc ${dpy},password'.\n");
+        if (!monitor_cur_is_qmp()) {
+            error_printf("If you want use passwords please enable "
+                         "password auth using '-vnc ${dpy},password'.\n");
+        }
         return -EINVAL;
     }
 
@@ -3570,9 +3572,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
         qapi_free_SocketAddress(addr);
         return;
     }
-    error_printf_unless_qmp("VNC server running on %s:%s\n",
-                            addr->u.inet.host,
-                            addr->u.inet.port);
+    if (!monitor_cur_is_qmp()) {
+        error_printf("VNC server running on %s:%s\n",
+                     addr->u.inet.host,
+                     addr->u.inet.port);
+    }
     qapi_free_SocketAddress(addr);
 }
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (8 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp() Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11  8:50   ` Richard Henderson
                     ` (2 more replies)
  2025-09-10 18:03 ` [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c Daniel P. Berrangé
                   ` (9 subsequent siblings)
  19 siblings, 3 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

These functions only had one caller which was easily converted to
the normal error_printf() function. Remove them as they don't add
sufficient value.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/monitor/monitor.h |  3 ---
 monitor/monitor.c         | 24 ------------------------
 stubs/error-printf.c      |  5 -----
 3 files changed, 32 deletions(-)

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index c3740ec616..296690e1f1 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -59,7 +59,4 @@ void monitor_register_hmp(const char *name, bool info,
 void monitor_register_hmp_info_hrt(const char *name,
                                    HumanReadableText *(*handler)(Error **errp));
 
-int error_vprintf_unless_qmp(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
-int error_printf_unless_qmp(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
-
 #endif /* MONITOR_H */
diff --git a/monitor/monitor.c b/monitor/monitor.c
index da54e1b1ce..03dbe5d131 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -281,30 +281,6 @@ int error_vprintf(const char *fmt, va_list ap)
     return vfprintf(stderr, fmt, ap);
 }
 
-int error_vprintf_unless_qmp(const char *fmt, va_list ap)
-{
-    Monitor *cur_mon = monitor_cur();
-
-    if (!cur_mon) {
-        return vfprintf(stderr, fmt, ap);
-    }
-    if (!monitor_cur_is_qmp()) {
-        return monitor_vprintf(cur_mon, fmt, ap);
-    }
-    return -1;
-}
-
-int error_printf_unless_qmp(const char *fmt, ...)
-{
-    va_list ap;
-    int ret;
-
-    va_start(ap, fmt);
-    ret = error_vprintf_unless_qmp(fmt, ap);
-    va_end(ap);
-    return ret;
-}
-
 static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
     /* Limit guest-triggerable events to 1 per second */
     [QAPI_EVENT_RTC_CHANGE]        = { 1000 * SCALE_MS },
diff --git a/stubs/error-printf.c b/stubs/error-printf.c
index 0e326d8010..1afa0f62ca 100644
--- a/stubs/error-printf.c
+++ b/stubs/error-printf.c
@@ -16,8 +16,3 @@ int error_vprintf(const char *fmt, va_list ap)
     }
     return vfprintf(stderr, fmt, ap);
 }
-
-int error_vprintf_unless_qmp(const char *fmt, va_list ap)
-{
-    return error_vprintf(fmt, ap);
-}
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (9 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11  8:55   ` Richard Henderson
  2025-09-19 12:27   ` Markus Armbruster
  2025-09-10 18:03 ` [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function Daniel P. Berrangé
                   ` (8 subsequent siblings)
  19 siblings, 2 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

This conceptually reverts 397d30e9401d2da96dbdf0ce49805d6d4bb68833.
The discussion around stubs in that commit does not appear to be
important to the current state of the codebase.

This makes the error_vprintf() impl source file match that
of error_printf(), and also match the header where it is declared.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 monitor/monitor.c              | 13 -------------
 stubs/monitor-core.c           |  5 +++++
 tests/unit/test-util-sockets.c |  1 +
 util/error-report.c            | 13 +++++++++++++
 4 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/monitor/monitor.c b/monitor/monitor.c
index 03dbe5d131..e1e5dbfcbe 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -268,19 +268,6 @@ void monitor_printc(Monitor *mon, int c)
     monitor_printf(mon, "'");
 }
 
-/*
- * Print to current monitor if we have one, else to stderr.
- */
-int error_vprintf(const char *fmt, va_list ap)
-{
-    Monitor *cur_mon = monitor_cur();
-
-    if (cur_mon && !monitor_cur_is_qmp()) {
-        return monitor_vprintf(cur_mon, fmt, ap);
-    }
-    return vfprintf(stderr, fmt, ap);
-}
-
 static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
     /* Limit guest-triggerable events to 1 per second */
     [QAPI_EVENT_RTC_CHANGE]        = { 1000 * SCALE_MS },
diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
index 1894cdfe1f..b498a0f1af 100644
--- a/stubs/monitor-core.c
+++ b/stubs/monitor-core.c
@@ -7,6 +7,11 @@ Monitor *monitor_cur(void)
     return NULL;
 }
 
+bool monitor_cur_is_qmp(void)
+{
+    return false;
+}
+
 Monitor *monitor_set_cur(Coroutine *co, Monitor *mon)
 {
     return NULL;
diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
index ee66d727c3..bd48731ea2 100644
--- a/tests/unit/test-util-sockets.c
+++ b/tests/unit/test-util-sockets.c
@@ -72,6 +72,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
  * otherwise we get duplicate syms at link time.
  */
 Monitor *monitor_cur(void) { return cur_mon; }
+bool monitor_cur_is_qmp(void) { return false; }
 Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
 int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
 
diff --git a/util/error-report.c b/util/error-report.c
index 1b17c11de1..79b6f23e64 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -29,6 +29,19 @@ bool message_with_timestamp;
 bool error_with_guestname;
 const char *error_guest_name;
 
+/*
+ * Print to current monitor if we have one, else to stderr.
+ */
+int error_vprintf(const char *fmt, va_list ap)
+{
+    Monitor *cur_mon = monitor_cur();
+
+    if (cur_mon && !monitor_cur_is_qmp()) {
+        return monitor_vprintf(cur_mon, fmt, ap);
+    }
+    return vfprintf(stderr, fmt, ap);
+}
+
 int error_printf(const char *fmt, ...)
 {
     va_list ap;
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (10 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 17:52   ` Richard Henderson
  2025-09-19 12:43   ` Markus Armbruster
  2025-09-10 18:03 ` [PATCH v3 13/20] util: don't skip error prefixes when QMP is active Daniel P. Berrangé
                   ` (7 subsequent siblings)
  19 siblings, 2 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().

This is undesirable because monitor_cur_is_qmp() will itself call
monitor_cur() again, and monitor_cur() must acquire locks and do
hash table lookups. Introducing a monitor_cur_hmp() helper will
combine the two operations into one reducing cost.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/monitor/monitor.h      |  1 +
 monitor/monitor.c              | 14 ++++++++++++++
 stubs/monitor-core.c           |  5 +++++
 tests/unit/test-util-sockets.c |  1 +
 4 files changed, 21 insertions(+)

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 296690e1f1..c3b79b960a 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -14,6 +14,7 @@ typedef struct MonitorOptions MonitorOptions;
 extern QemuOptsList qemu_mon_opts;
 
 Monitor *monitor_cur(void);
+Monitor *monitor_cur_hmp(void);
 Monitor *monitor_set_cur(Coroutine *co, Monitor *mon);
 bool monitor_cur_is_qmp(void);
 
diff --git a/monitor/monitor.c b/monitor/monitor.c
index e1e5dbfcbe..cff502c53e 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -84,6 +84,20 @@ Monitor *monitor_cur(void)
     return mon;
 }
 
+Monitor *monitor_cur_hmp(void)
+{
+    Monitor *mon;
+
+    qemu_mutex_lock(&monitor_lock);
+    mon = g_hash_table_lookup(coroutine_mon, qemu_coroutine_self());
+    if (mon && monitor_is_qmp(mon)) {
+        mon = NULL;
+    }
+    qemu_mutex_unlock(&monitor_lock);
+
+    return mon;
+}
+
 /**
  * Sets a new current monitor and returns the old one.
  *
diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
index b498a0f1af..1e0b11ec29 100644
--- a/stubs/monitor-core.c
+++ b/stubs/monitor-core.c
@@ -7,6 +7,11 @@ Monitor *monitor_cur(void)
     return NULL;
 }
 
+Monitor *monitor_cur_hmp(void)
+{
+    return NULL;
+}
+
 bool monitor_cur_is_qmp(void)
 {
     return false;
diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
index bd48731ea2..d40813c682 100644
--- a/tests/unit/test-util-sockets.c
+++ b/tests/unit/test-util-sockets.c
@@ -72,6 +72,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
  * otherwise we get duplicate syms at link time.
  */
 Monitor *monitor_cur(void) { return cur_mon; }
+Monitor *monitor_cur_hmp(void) { return cur_mon; }
 bool monitor_cur_is_qmp(void) { return false; }
 Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
 int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 13/20] util: don't skip error prefixes when QMP is active
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (11 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-22  8:43   ` Markus Armbruster
  2025-09-10 18:03 ` [PATCH v3 14/20] util: fix interleaving of error & trace output Daniel P. Berrangé
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The vreport() function will print to HMP if available, otherwise
to stderr. In the event that vreport() is called during execution
of a QMP command, it will print to stderr, but mistakenly omit the
message prefixes (timestamp, guest name, program name).

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 util/error-report.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/util/error-report.c b/util/error-report.c
index 79b6f23e64..c0fcf388de 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -34,9 +34,9 @@ const char *error_guest_name;
  */
 int error_vprintf(const char *fmt, va_list ap)
 {
-    Monitor *cur_mon = monitor_cur();
+    Monitor *cur_mon = monitor_cur_hmp();
 
-    if (cur_mon && !monitor_cur_is_qmp()) {
+    if (cur_mon) {
         return monitor_vprintf(cur_mon, fmt, ap);
     }
     return vfprintf(stderr, fmt, ap);
@@ -157,7 +157,7 @@ static void print_loc(void)
     int i;
     const char *const *argp;
 
-    if (!monitor_cur() && g_get_prgname()) {
+    if (!monitor_cur_hmp() && g_get_prgname()) {
         error_printf("%s:", g_get_prgname());
         sep = " ";
     }
@@ -201,14 +201,14 @@ static void vreport(report_type type, const char *fmt, va_list ap)
 {
     gchar *timestr;
 
-    if (message_with_timestamp && !monitor_cur()) {
+    if (message_with_timestamp && !monitor_cur_hmp()) {
         timestr = real_time_iso8601();
         error_printf("%s ", timestr);
         g_free(timestr);
     }
 
     /* Only prepend guest name if -msg guest-name and -name guest=... are set */
-    if (error_with_guestname && error_guest_name && !monitor_cur()) {
+    if (error_with_guestname && error_guest_name && !monitor_cur_hmp()) {
         error_printf("%s ", error_guest_name);
     }
 
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 14/20] util: fix interleaving of error & trace output
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (12 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 13/20] util: don't skip error prefixes when QMP is active Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 18:01   ` Richard Henderson
                     ` (2 more replies)
  2025-09-10 18:03 ` [PATCH v3 15/20] util: introduce common helper for error-report & log code Daniel P. Berrangé
                   ` (5 subsequent siblings)
  19 siblings, 3 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The monitor_cur_hmp() function will acquire/release mutex locks, which
will trigger trace probes, which can in turn trigger qemu_log() calls.
vreport() calls monitor_cur() multiple times through its execution
both directly and indirectly via error_vprintf().

The result is that the prefix information printed by vreport() gets
interleaved with qemu_log() output, when run outside the context of
an HMP command dispatcher. This can be seen with:

 $ qemu-system-x86_64
     -msg timestamp=on,guest-name=on
     -display none
     -object tls-creds-x509,id=f,dir=fish
     -name fish
     -d trace:qemu_mutex*
   2025-09-10T16:30:42.514374Z qemu_mutex_unlock released mutex 0x560b0339b4c0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:30:42.514400Z qemu_mutex_lock waiting on mutex 0x560b033983e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:30:42.514402Z qemu_mutex_locked taken mutex 0x560b033983e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:30:42.514404Z qemu_mutex_unlock released mutex 0x560b033983e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:30:42.516716Z qemu_mutex_lock waiting on mutex 0x560b03398560 (../monitor/monitor.c:91)
   2025-09-10T16:30:42.516723Z qemu_mutex_locked taken mutex 0x560b03398560 (../monitor/monitor.c:91)
   2025-09-10T16:30:42.516726Z qemu_mutex_unlock released mutex 0x560b03398560 (../monitor/monitor.c:96)
   2025-09-10T16:30:42.516728Z qemu_mutex_lock waiting on mutex 0x560b03398560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842057Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842058Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
   2025-09-10T16:31:04.842055Z 2025-09-10T16:31:04.842060Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842061Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842062Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
   2025-09-10T16:31:04.842064Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842065Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842066Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
   fish 2025-09-10T16:31:04.842068Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842069Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842070Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
   2025-09-10T16:31:04.842072Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842097Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842099Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
   qemu-system-x86_64:2025-09-10T16:31:04.842100Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842102Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842103Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
    2025-09-10T16:31:04.842105Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842106Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842107Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
   Unable to access credentials fish/ca-cert.pem: No such file or directory2025-09-10T16:31:04.842109Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842110Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
   2025-09-10T16:31:04.842111Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)

To avoid this interleaving (as well as reduce the huge number of
mutex lock/unlock calls) we need to ensure that monitor_cur_hmp() is
only called once at the start of vreport(), and if no HMP is present,
no further monitor APIs can be called.

This implies error_[v]printf() cannot be called from vreport().

Instead a decision about whether output will go to monitor_[v]printf()
or fprintf() must be made upfront, and then those functions called
directly.

 $ qemu-system-x86_64
     -msg timestamp=on,guest-name=on
     -display none
     -object tls-creds-x509,id=f,dir=fish
     -name fish
     -d trace:qemu_mutex*
   2025-09-10T16:31:22.701691Z qemu_mutex_unlock released mutex 0x5626fd3b84c0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:31:22.701728Z qemu_mutex_lock waiting on mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:31:22.701730Z qemu_mutex_locked taken mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:31:22.701732Z qemu_mutex_unlock released mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
   2025-09-10T16:31:22.703989Z qemu_mutex_lock waiting on mutex 0x5626fd3b5560 (../monitor/monitor.c:91)
   2025-09-10T16:31:22.703996Z qemu_mutex_locked taken mutex 0x5626fd3b5560 (../monitor/monitor.c:91)
   2025-09-10T16:31:22.703999Z qemu_mutex_unlock released mutex 0x5626fd3b5560 (../monitor/monitor.c:96)
   2025-09-10T16:31:22.704000Z fish qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

This change requires adding a stub for monitor_printf() since that
is now called directly by vreport(), where monitor_vprintf() was
only needed previously.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 stubs/monitor-core.c           |  5 +++
 tests/unit/test-util-sockets.c |  1 +
 util/error-report.c            | 60 ++++++++++++++++++++++++----------
 3 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
index 1e0b11ec29..70b1f7a994 100644
--- a/stubs/monitor-core.c
+++ b/stubs/monitor-core.c
@@ -30,3 +30,8 @@ int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 {
     abort();
 }
+
+int monitor_printf(Monitor *mon, const char *fmt, ...)
+{
+    abort();
+}
diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
index d40813c682..53733163dd 100644
--- a/tests/unit/test-util-sockets.c
+++ b/tests/unit/test-util-sockets.c
@@ -76,6 +76,7 @@ Monitor *monitor_cur_hmp(void) { return cur_mon; }
 bool monitor_cur_is_qmp(void) { return false; }
 Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
 int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
+int monitor_printf(Monitor *mon, const char *fmt, ...) { abort(); }
 
 #ifndef _WIN32
 static void test_socket_fd_pass_name_good(void)
diff --git a/util/error-report.c b/util/error-report.c
index c0fcf388de..6c887047e3 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -29,6 +29,9 @@ bool message_with_timestamp;
 bool error_with_guestname;
 const char *error_guest_name;
 
+typedef void (*error_print_func)(void *opaque, const char *fmt, ...);
+typedef void (*error_print_vfunc)(void *opaque, const char *fmt, va_list ap);
+
 /*
  * Print to current monitor if we have one, else to stderr.
  */
@@ -151,34 +154,34 @@ void loc_set_file(const char *fname, int lno)
 /*
  * Print current location to current monitor if we have one, else to stderr.
  */
-static void print_loc(void)
+static void print_loc(bool cur, error_print_func print_func, void *print_opaque)
 {
     const char *sep = "";
     int i;
     const char *const *argp;
 
-    if (!monitor_cur_hmp() && g_get_prgname()) {
-        error_printf("%s:", g_get_prgname());
+    if (!cur && g_get_prgname()) {
+        print_func(print_opaque, "%s:", g_get_prgname());
         sep = " ";
     }
     switch (cur_loc->kind) {
     case LOC_CMDLINE:
         argp = cur_loc->ptr;
         for (i = 0; i < cur_loc->num; i++) {
-            error_printf("%s%s", sep, argp[i]);
+            print_func(print_opaque, "%s%s", sep, argp[i]);
             sep = " ";
         }
-        error_printf(": ");
+        print_func(print_opaque, ": ");
         break;
     case LOC_FILE:
-        error_printf("%s:", (const char *)cur_loc->ptr);
+        print_func(print_opaque, "%s:", (const char *)cur_loc->ptr);
         if (cur_loc->num) {
-            error_printf("%d:", cur_loc->num);
+            print_func(print_opaque, "%d:", cur_loc->num);
         }
-        error_printf(" ");
+        print_func(print_opaque, " ");
         break;
     default:
-        error_printf("%s", sep);
+        print_func(print_opaque, "%s", sep);
     }
 }
 
@@ -199,34 +202,55 @@ real_time_iso8601(void)
 G_GNUC_PRINTF(2, 0)
 static void vreport(report_type type, const char *fmt, va_list ap)
 {
+    /*
+     * Calling monitor_cur_hmp() will acquire/release mutexes,
+     * which triggers trace probes, which can trigger
+     * qemu_log calls, which would interleave with output
+     * from this. Hence cache the monitor handle upfront
+     * so any tracing appears before we start outputting.
+     */
+    Monitor *cur = monitor_cur_hmp();
+    error_print_func print_func;
+    error_print_vfunc print_vfunc;
+    void *print_opaque;
     gchar *timestr;
 
-    if (message_with_timestamp && !monitor_cur_hmp()) {
+    if (cur) {
+        print_func = (error_print_func)monitor_printf;
+        print_vfunc = (error_print_vfunc)monitor_vprintf;
+        print_opaque = cur;
+    } else {
+        print_func = (error_print_func)fprintf;
+        print_vfunc = (error_print_vfunc)vfprintf;
+        print_opaque = stderr;
+    }
+
+    if (message_with_timestamp && !cur) {
         timestr = real_time_iso8601();
-        error_printf("%s ", timestr);
+        print_func(print_opaque, "%s ", timestr);
         g_free(timestr);
     }
 
     /* Only prepend guest name if -msg guest-name and -name guest=... are set */
-    if (error_with_guestname && error_guest_name && !monitor_cur_hmp()) {
-        error_printf("%s ", error_guest_name);
+    if (error_with_guestname && error_guest_name && !cur) {
+        print_func(print_opaque, "%s ", error_guest_name);
     }
 
-    print_loc();
+    print_loc(!!cur, print_func, print_opaque);
 
     switch (type) {
     case REPORT_TYPE_ERROR:
         break;
     case REPORT_TYPE_WARNING:
-        error_printf("warning: ");
+        print_func(print_opaque, "warning: ");
         break;
     case REPORT_TYPE_INFO:
-        error_printf("info: ");
+        print_func(print_opaque, "info: ");
         break;
     }
 
-    error_vprintf(fmt, ap);
-    error_printf("\n");
+    print_vfunc(print_opaque, fmt, ap);
+    print_func(print_opaque, "\n");
 }
 
 /*
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 15/20] util: introduce common helper for error-report & log code
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (13 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 14/20] util: fix interleaving of error & trace output Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 18:02   ` Richard Henderson
  2025-09-10 18:03 ` [PATCH v3 16/20] util: convert error-report & log to message API for timestamp Daniel P. Berrangé
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The error-report and log code both have a need to add prefixes
to messages they are printing, with the current example being
a timestamp.

The format and configuration they use should be consistent, so
providing a common helper will ensure this is always the case.
Initially the helper only emits a timestamp, but future patches
will expand this.

This takes the liberty of assigning the new file to the same
maintainer as the existing error-report.c file, given it will
be extracting some functionality from the latter.

While vreport() dynamically changes between reporting to the
monitor vs stderr, depending on whether HMP is active or not,
message prefixes are only ever used in the non-HMP case. Thus
the helper API can take a FILE * object and not have to deal
with the monitor at all.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 MAINTAINERS            |  2 ++
 include/qemu/message.h | 28 ++++++++++++++++++++++++++++
 util/meson.build       |  1 +
 util/message.c         | 23 +++++++++++++++++++++++
 4 files changed, 54 insertions(+)
 create mode 100644 include/qemu/message.h
 create mode 100644 util/message.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1ae28e8804..5af014ca45 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3171,9 +3171,11 @@ M: Markus Armbruster <armbru@redhat.com>
 S: Supported
 F: include/qapi/error.h
 F: include/qemu/error-report.h
+F: include/qemu/message.h
 F: qapi/error.json
 F: util/error.c
 F: util/error-report.c
+F: util/message.c
 F: scripts/coccinelle/err-bad-newline.cocci
 F: scripts/coccinelle/error-use-after-free.cocci
 F: scripts/coccinelle/error_propagate_null.cocci
diff --git a/include/qemu/message.h b/include/qemu/message.h
new file mode 100644
index 0000000000..0a06421f77
--- /dev/null
+++ b/include/qemu/message.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef QEMU_MESSAGE_H
+#define QEMU_MESSAGE_H
+
+enum QMessageFormatFlags {
+    QMESSAGE_FORMAT_TIMESTAMP = (1 << 0),
+};
+
+/**
+ * qmessage_set_format:
+ * @flags: the message information to emit
+ *
+ * Select which pieces of information to
+ * emit for messages
+ */
+void qmessage_set_format(int flags);
+
+/**
+ * qmessage_context_print:
+ * @fp: file to emit the prefix on
+ *
+ * Emit a message prefix with the information selected by
+ * an earlier call to qmessage_set_format.
+ */
+void qmessage_context_print(FILE *fp);
+
+#endif /* QEMU_MESSAGE_H */
diff --git a/util/meson.build b/util/meson.build
index 35029380a3..f5365e3b4f 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -40,6 +40,7 @@ util_ss.add(files('host-utils.c'))
 util_ss.add(files('bitmap.c', 'bitops.c'))
 util_ss.add(files('fifo8.c'))
 util_ss.add(files('cacheflush.c'))
+util_ss.add(files('message.c'))
 util_ss.add(files('error.c', 'error-report.c'))
 util_ss.add(files('qemu-print.c'))
 util_ss.add(files('id.c'))
diff --git a/util/message.c b/util/message.c
new file mode 100644
index 0000000000..ef70e08c5f
--- /dev/null
+++ b/util/message.c
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "qemu/osdep.h"
+
+#include "qemu/message.h"
+#include "monitor/monitor.h"
+
+static int message_format;
+
+void qmessage_set_format(int flags)
+{
+    message_format = flags;
+}
+
+void qmessage_context_print(FILE *fp)
+{
+
+    if (message_format & QMESSAGE_FORMAT_TIMESTAMP) {
+        g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
+        g_autofree char *timestr = g_date_time_format_iso8601(dt);
+        fprintf(fp, "%s ", timestr);
+    }
+}
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 16/20] util: convert error-report & log to message API for timestamp
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (14 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 15/20] util: introduce common helper for error-report & log code Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 18:04   ` Richard Henderson
  2025-09-10 18:03 ` [PATCH v3 17/20] util: add support for formatting a workload name in messages Daniel P. Berrangé
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

Both the error-report and log APIs can optional emit a timestamp
as a prefix on messages, with the '-msg timestamp=on' command
line flag is set.

Convert them to the new message API for formatting the context
prefix, guaranteeing they will have matching behaviour going
forward.

There is no change in output format for either logs or errors
with this conversion.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/error-report.h    |  1 -
 system/vl.c                    |  7 ++++++-
 tests/unit/test-error-report.c |  3 ++-
 util/error-report.c            | 17 ++---------------
 util/log.c                     | 21 ++++-----------------
 5 files changed, 14 insertions(+), 35 deletions(-)

diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h
index 3ae2357fda..c8000778ec 100644
--- a/include/qemu/error-report.h
+++ b/include/qemu/error-report.h
@@ -70,7 +70,6 @@ void error_init(const char *argv0);
                               fmt, ##__VA_ARGS__);      \
     })
 
-extern bool message_with_timestamp;
 extern bool error_with_guestname;
 extern const char *error_guest_name;
 
diff --git a/system/vl.c b/system/vl.c
index a64fd90d4a..696dd92669 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -26,6 +26,7 @@
 #include "qemu/help-texts.h"
 #include "qemu/datadir.h"
 #include "qemu/units.h"
+#include "qemu/message.h"
 #include "qemu/module.h"
 #include "qemu/target-info.h"
 #include "exec/cpu-common.h"
@@ -813,8 +814,12 @@ static void realtime_init(void)
 
 static void configure_msg(QemuOpts *opts)
 {
-    message_with_timestamp = qemu_opt_get_bool(opts, "timestamp", false);
+    int flags = 0;
+    if (qemu_opt_get_bool(opts, "timestamp", false)) {
+        flags |= QMESSAGE_FORMAT_TIMESTAMP;
+    }
     error_with_guestname = qemu_opt_get_bool(opts, "guest-name", false);
+    qmessage_set_format(flags);
 }
 
 
diff --git a/tests/unit/test-error-report.c b/tests/unit/test-error-report.c
index 54319c86c9..78f8b57660 100644
--- a/tests/unit/test-error-report.c
+++ b/tests/unit/test-error-report.c
@@ -13,6 +13,7 @@
 
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "qemu/message.h"
 
 static void
 test_error_report_simple(void)
@@ -90,7 +91,7 @@ static void
 test_error_report_timestamp(void)
 {
     if (g_test_subprocess()) {
-        message_with_timestamp = true;
+        qmessage_set_format(QMESSAGE_FORMAT_TIMESTAMP);
         warn_report("warn");
         error_report("err");
         return;
diff --git a/util/error-report.c b/util/error-report.c
index 6c887047e3..719f059494 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -13,6 +13,7 @@
 #include "qemu/osdep.h"
 #include "monitor/monitor.h"
 #include "qemu/error-report.h"
+#include "qemu/message.h"
 
 /*
  * @report_type is the type of message: error, warning or
@@ -24,8 +25,6 @@ typedef enum {
     REPORT_TYPE_INFO,
 } report_type;
 
-/* Prepend timestamp to messages */
-bool message_with_timestamp;
 bool error_with_guestname;
 const char *error_guest_name;
 
@@ -185,13 +184,6 @@ static void print_loc(bool cur, error_print_func print_func, void *print_opaque)
     }
 }
 
-static char *
-real_time_iso8601(void)
-{
-    g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
-    return g_date_time_format_iso8601(dt);
-}
-
 /*
  * Print a message to current monitor if we have one, else to stderr.
  * @report_type is the type of message: error, warning or informational.
@@ -213,7 +205,6 @@ static void vreport(report_type type, const char *fmt, va_list ap)
     error_print_func print_func;
     error_print_vfunc print_vfunc;
     void *print_opaque;
-    gchar *timestr;
 
     if (cur) {
         print_func = (error_print_func)monitor_printf;
@@ -223,12 +214,8 @@ static void vreport(report_type type, const char *fmt, va_list ap)
         print_func = (error_print_func)fprintf;
         print_vfunc = (error_print_vfunc)vfprintf;
         print_opaque = stderr;
-    }
 
-    if (message_with_timestamp && !cur) {
-        timestr = real_time_iso8601();
-        print_func(print_opaque, "%s ", timestr);
-        g_free(timestr);
+        qmessage_context_print(stderr);
     }
 
     /* Only prepend guest name if -msg guest-name and -name guest=... are set */
diff --git a/util/log.c b/util/log.c
index 2642a55c59..baa33ad8f1 100644
--- a/util/log.c
+++ b/util/log.c
@@ -22,6 +22,7 @@
 #include "qemu/range.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "qemu/message.h"
 #include "qemu/cutils.h"
 #include "trace/control.h"
 #include "qemu/thread.h"
@@ -151,26 +152,12 @@ static __thread bool incomplete;
 
 void qemu_log(const char *fmt, ...)
 {
-    FILE *f;
-    g_autofree const char *timestr = NULL;
-
-    /*
-     * Prepare the timestamp *outside* the logging
-     * lock so it better reflects when the message
-     * was emitted if we are delayed acquiring the
-     * mutex
-     */
-    if (message_with_timestamp && !incomplete) {
-        g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
-        timestr = g_date_time_format_iso8601(dt);
-    }
-
-    f = qemu_log_trylock();
+    FILE *f = qemu_log_trylock();
     if (f) {
         va_list ap;
 
-        if (timestr) {
-            fprintf(f, "%s ", timestr);
+        if (!incomplete) {
+            qmessage_context_print(f);
         }
 
         va_start(ap, fmt);
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 17/20] util: add support for formatting a workload name in messages
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (15 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 16/20] util: convert error-report & log to message API for timestamp Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 18:06   ` Richard Henderson
  2025-09-11 20:27   ` Dr. David Alan Gilbert
  2025-09-10 18:03 ` [PATCH v3 18/20] util: add support for formatting a program " Daniel P. Berrangé
                   ` (2 subsequent siblings)
  19 siblings, 2 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The error_report function can include the guest name in any
messages it prints. The qemu_log function has no equivalent
behaviour.

This introduces support for a "workload name" in the new
messages API, which in the case of system emulators will
be the guest name. The possibility of defining a workload
name for other binaries is left as an exercise for the
future.

This change has no impact on the output of the error_report
function, but will change the qemu_log function. This can
be easily seen with the 'log' trace backend, and how it is
now more closely matching error_report output.

Before:

  # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
  qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
  qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
  blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

After:

  # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
  blah qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
  blah qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
  blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/error-report.h |  3 ---
 include/qemu/message.h      | 10 ++++++++++
 system/vl.c                 |  6 ++++--
 util/error-report.c         |  7 -------
 util/message.c              | 12 +++++++++++-
 5 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h
index c8000778ec..ffc305f828 100644
--- a/include/qemu/error-report.h
+++ b/include/qemu/error-report.h
@@ -70,7 +70,4 @@ void error_init(const char *argv0);
                               fmt, ##__VA_ARGS__);      \
     })
 
-extern bool error_with_guestname;
-extern const char *error_guest_name;
-
 #endif
diff --git a/include/qemu/message.h b/include/qemu/message.h
index 0a06421f77..cfc3c92648 100644
--- a/include/qemu/message.h
+++ b/include/qemu/message.h
@@ -5,6 +5,7 @@
 
 enum QMessageFormatFlags {
     QMESSAGE_FORMAT_TIMESTAMP = (1 << 0),
+    QMESSAGE_FORMAT_WORKLOAD_NAME = (1 << 1),
 };
 
 /**
@@ -16,6 +17,15 @@ enum QMessageFormatFlags {
  */
 void qmessage_set_format(int flags);
 
+/**
+ * qmessage_set_workload_name:
+ * @name: the name of the workload
+ *
+ * Set the workload name, which for a system emulator
+ * will be the guest VM name.
+ */
+void qmessage_set_workload_name(const char *name);
+
 /**
  * qmessage_context_print:
  * @fp: file to emit the prefix on
diff --git a/system/vl.c b/system/vl.c
index 696dd92669..fee6fdf7b1 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -818,7 +818,9 @@ static void configure_msg(QemuOpts *opts)
     if (qemu_opt_get_bool(opts, "timestamp", false)) {
         flags |= QMESSAGE_FORMAT_TIMESTAMP;
     }
-    error_with_guestname = qemu_opt_get_bool(opts, "guest-name", false);
+    if (qemu_opt_get_bool(opts, "guest-name", false)) {
+        flags |= QMESSAGE_FORMAT_WORKLOAD_NAME;
+    }
     qmessage_set_format(flags);
 }
 
@@ -3520,7 +3522,7 @@ void qemu_init(int argc, char **argv)
                     exit(1);
                 }
                 /* Capture guest name if -msg guest-name is used later */
-                error_guest_name = qemu_opt_get(opts, "guest");
+                qmessage_set_workload_name(qemu_opt_get(opts, "guest"));
                 break;
             case QEMU_OPTION_prom_env:
                 if (nb_prom_envs >= MAX_PROM_ENVS) {
diff --git a/util/error-report.c b/util/error-report.c
index 719f059494..c40cdf3bb3 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -25,8 +25,6 @@ typedef enum {
     REPORT_TYPE_INFO,
 } report_type;
 
-bool error_with_guestname;
-const char *error_guest_name;
 
 typedef void (*error_print_func)(void *opaque, const char *fmt, ...);
 typedef void (*error_print_vfunc)(void *opaque, const char *fmt, va_list ap);
@@ -218,11 +216,6 @@ static void vreport(report_type type, const char *fmt, va_list ap)
         qmessage_context_print(stderr);
     }
 
-    /* Only prepend guest name if -msg guest-name and -name guest=... are set */
-    if (error_with_guestname && error_guest_name && !cur) {
-        print_func(print_opaque, "%s ", error_guest_name);
-    }
-
     print_loc(!!cur, print_func, print_opaque);
 
     switch (type) {
diff --git a/util/message.c b/util/message.c
index ef70e08c5f..a91c008e08 100644
--- a/util/message.c
+++ b/util/message.c
@@ -6,18 +6,28 @@
 #include "monitor/monitor.h"
 
 static int message_format;
+static char *message_workloadname;
 
 void qmessage_set_format(int flags)
 {
     message_format = flags;
 }
 
-void qmessage_context_print(FILE *fp)
+void qmessage_set_workload_name(const char *name)
 {
+    message_workloadname = g_strdup(name);
+}
 
+void qmessage_context_print(FILE *fp)
+{
     if (message_format & QMESSAGE_FORMAT_TIMESTAMP) {
         g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
         g_autofree char *timestr = g_date_time_format_iso8601(dt);
         fprintf(fp, "%s ", timestr);
     }
+
+    if ((message_format & QMESSAGE_FORMAT_WORKLOAD_NAME) &&
+        message_workloadname) {
+        fprintf(fp, "%s ", message_workloadname);
+    }
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 18/20] util: add support for formatting a program name in messages
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (16 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 17/20] util: add support for formatting a workload name in messages Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 18:07   ` Richard Henderson
  2025-09-10 18:03 ` [PATCH v3 19/20] util: add support for formatting thread info " Daniel P. Berrangé
  2025-09-10 18:03 ` [PATCH v3 20/20] util: add brackets around guest name in message context Daniel P. Berrangé
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The error_report function can include the program name in any
messages it prints. The qemu_log function has no equivalent
behaviour.

This introduces support for a "program name" in the new
messages API, which will be included by default for all
binaries.

This change tweaks the output of the error_report function,
adding a space between the program name and the location
info. The qemu_log function will gain the program name. This
can be easily seen with the 'log' trace backend, and how it
is now more closely matching error_report output.

Before:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
  qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x5584e13937f0 dir=fish
  qcrypto_tls_creds_get_path TLS creds path creds=0x5584e13937f0 filename=ca-cert.pem path=<none>
  qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

After:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
  qemu-system-x86_64: qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x5584e13937f0 dir=fish
  qemu-system-x86_64: qcrypto_tls_creds_get_path TLS creds path creds=0x5584e13937f0 filename=ca-cert.pem path=<none>
  qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/message.h         | 1 +
 system/vl.c                    | 2 +-
 tests/unit/test-error-report.c | 5 +++--
 util/error-report.c            | 4 ----
 util/message.c                 | 9 ++++++++-
 5 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/include/qemu/message.h b/include/qemu/message.h
index cfc3c92648..b8518d06be 100644
--- a/include/qemu/message.h
+++ b/include/qemu/message.h
@@ -6,6 +6,7 @@
 enum QMessageFormatFlags {
     QMESSAGE_FORMAT_TIMESTAMP = (1 << 0),
     QMESSAGE_FORMAT_WORKLOAD_NAME = (1 << 1),
+    QMESSAGE_FORMAT_PROGRAM_NAME = (1 << 2),
 };
 
 /**
diff --git a/system/vl.c b/system/vl.c
index fee6fdf7b1..9030212c50 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -814,7 +814,7 @@ static void realtime_init(void)
 
 static void configure_msg(QemuOpts *opts)
 {
-    int flags = 0;
+    int flags = QMESSAGE_FORMAT_PROGRAM_NAME;
     if (qemu_opt_get_bool(opts, "timestamp", false)) {
         flags |= QMESSAGE_FORMAT_TIMESTAMP;
     }
diff --git a/tests/unit/test-error-report.c b/tests/unit/test-error-report.c
index 78f8b57660..3987a8ed25 100644
--- a/tests/unit/test-error-report.c
+++ b/tests/unit/test-error-report.c
@@ -48,7 +48,7 @@ test_error_report_loc(void)
     g_test_trap_subprocess(NULL, 0, 0);
     g_test_trap_assert_passed();
     g_test_trap_assert_stderr("\
-test-error-report:some-file.c:7717: test error1*\
+test-error-report: some-file.c:7717: test error1*\
 test-error-report: test error2*\
 ");
 }
@@ -91,7 +91,8 @@ static void
 test_error_report_timestamp(void)
 {
     if (g_test_subprocess()) {
-        qmessage_set_format(QMESSAGE_FORMAT_TIMESTAMP);
+        qmessage_set_format(QMESSAGE_FORMAT_TIMESTAMP |
+                            QMESSAGE_FORMAT_PROGRAM_NAME);
         warn_report("warn");
         error_report("err");
         return;
diff --git a/util/error-report.c b/util/error-report.c
index c40cdf3bb3..d3a234b8b9 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -157,10 +157,6 @@ static void print_loc(bool cur, error_print_func print_func, void *print_opaque)
     int i;
     const char *const *argp;
 
-    if (!cur && g_get_prgname()) {
-        print_func(print_opaque, "%s:", g_get_prgname());
-        sep = " ";
-    }
     switch (cur_loc->kind) {
     case LOC_CMDLINE:
         argp = cur_loc->ptr;
diff --git a/util/message.c b/util/message.c
index a91c008e08..1db9254733 100644
--- a/util/message.c
+++ b/util/message.c
@@ -5,7 +5,7 @@
 #include "qemu/message.h"
 #include "monitor/monitor.h"
 
-static int message_format;
+static int message_format = QMESSAGE_FORMAT_PROGRAM_NAME;
 static char *message_workloadname;
 
 void qmessage_set_format(int flags)
@@ -30,4 +30,11 @@ void qmessage_context_print(FILE *fp)
         message_workloadname) {
         fprintf(fp, "%s ", message_workloadname);
     }
+
+    if (message_format & QMESSAGE_FORMAT_PROGRAM_NAME) {
+        const char *pgnamestr = g_get_prgname();
+        if (pgnamestr) {
+            fprintf(fp, "%s: ", pgnamestr);
+        }
+    }
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 19/20] util: add support for formatting thread info in messages
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (17 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 18/20] util: add support for formatting a program " Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 18:11   ` Richard Henderson
  2025-09-10 18:03 ` [PATCH v3 20/20] util: add brackets around guest name in message context Daniel P. Berrangé
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The message context is now extended to be able to include the
thread ID and thread name, after the program name. On Linux
the thread ID will match the process TID visible in /proc,
while on other platforms it will merely be an integer repr
of the system thread object address/ID.

This changes the output for both error_report and qemu_log,
when running under the system emulators or the QEMU storage
daemon. Other programs omit the thread information since
they are largely single threaded, though potentially it
would be useful to enable in all of them, given that the RCU
thread will always get spawned by a constructor function.

Before:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
  qemu-system-x86_64: qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x560db818e080 dir=fish
  qemu-system-x86_64: qcrypto_tls_creds_get_path TLS creds path creds=0x560db818e080 filename=ca-cert.pem path=<none>
  qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory

After:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
  qemu-system-x86_64(772366:main): qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x560db818e080 dir=fish
  qemu-system-x86_64(772366:main): qcrypto_tls_creds_get_path TLS creds path creds=0x560db818e080 filename=ca-cert.pem path=<none>
  qemu-system-x86_64(772366:main): Unable to access credentials fish/ca-cert.pem: No such file or directory

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 include/qemu/message.h               | 1 +
 storage-daemon/qemu-storage-daemon.c | 6 ++++++
 system/vl.c                          | 8 ++++++--
 tests/qemu-iotests/041               | 2 +-
 tests/qemu-iotests/common.filter     | 2 +-
 util/message.c                       | 7 +++++++
 6 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/include/qemu/message.h b/include/qemu/message.h
index b8518d06be..2cc092c993 100644
--- a/include/qemu/message.h
+++ b/include/qemu/message.h
@@ -7,6 +7,7 @@ enum QMessageFormatFlags {
     QMESSAGE_FORMAT_TIMESTAMP = (1 << 0),
     QMESSAGE_FORMAT_WORKLOAD_NAME = (1 << 1),
     QMESSAGE_FORMAT_PROGRAM_NAME = (1 << 2),
+    QMESSAGE_FORMAT_THREAD_INFO = (1 << 3),
 };
 
 /**
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
index eb72561358..cc44ed7848 100644
--- a/storage-daemon/qemu-storage-daemon.c
+++ b/storage-daemon/qemu-storage-daemon.c
@@ -47,6 +47,7 @@
 #include "qemu/cutils.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
+#include "qemu/message.h"
 #include "qemu/help_option.h"
 #include "qemu/job.h"
 #include "qemu/log.h"
@@ -65,6 +66,10 @@ static const char *pid_file;
 static char *pid_file_realpath;
 static volatile bool exit_requested = false;
 
+#define QMESSAGE_FORMAT_DEFAULT \
+    (QMESSAGE_FORMAT_PROGRAM_NAME | \
+     QMESSAGE_FORMAT_THREAD_INFO)
+
 void qemu_system_killed(int signal, pid_t pid)
 {
     exit_requested = true;
@@ -399,6 +404,7 @@ int main(int argc, char *argv[])
 #endif
 
     error_init(argv[0]);
+    qmessage_set_format(QMESSAGE_FORMAT_DEFAULT);
     qemu_init_exec_dir(argv[0]);
     os_setup_signal_handling();
 
diff --git a/system/vl.c b/system/vl.c
index 9030212c50..20b655a7bc 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -145,6 +145,10 @@
 
 #define MAX_VIRTIO_CONSOLES 1
 
+#define QMESSAGE_FORMAT_DEFAULT \
+    (QMESSAGE_FORMAT_PROGRAM_NAME | \
+     QMESSAGE_FORMAT_THREAD_INFO)
+
 typedef struct BlockdevOptionsQueueEntry {
     BlockdevOptions *bdo;
     Location loc;
@@ -811,10 +815,9 @@ static void realtime_init(void)
     }
 }
 
-
 static void configure_msg(QemuOpts *opts)
 {
-    int flags = QMESSAGE_FORMAT_PROGRAM_NAME;
+    int flags = QMESSAGE_FORMAT_DEFAULT;
     if (qemu_opt_get_bool(opts, "timestamp", false)) {
         flags |= QMESSAGE_FORMAT_TIMESTAMP;
     }
@@ -2888,6 +2891,7 @@ void qemu_init(int argc, char **argv)
     module_call_init(MODULE_INIT_OPTS);
 
     error_init(argv[0]);
+    qmessage_set_format(QMESSAGE_FORMAT_DEFAULT);
     qemu_init_exec_dir(argv[0]);
 
     os_setup_limits();
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 8452845f44..dc2666afe7 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -1102,7 +1102,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
         self.vm.shutdown()
         log = iotests.filter_qtest(self.vm.get_log())
         log = re.sub(r'^Formatting.*\n', '', log)
-        log = re.sub(r'^%s: ' % os.path.basename(iotests.qemu_prog), '', log)
+        log = re.sub(r'^%s: \(\d+:\w+\): ' % os.path.basename(iotests.qemu_prog), '', log)
 
         self.assertEqual(log,
                          "Can no longer replace 'img1' by 'repair0', because " +
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 511a55b1e8..84f352d30b 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -81,7 +81,7 @@ _filter_qemu_io()
 # replace occurrences of QEMU_PROG with "qemu"
 _filter_qemu()
 {
-    gsed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" \
+    gsed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG): ([0-9]\+:[-_a-zA-Z]\+):#\1QEMU_PROG:#" \
         -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#' \
         -e $'s#\r##' # QEMU monitor uses \r\n line endings
 }
diff --git a/util/message.c b/util/message.c
index 1db9254733..814ca0316e 100644
--- a/util/message.c
+++ b/util/message.c
@@ -37,4 +37,11 @@ void qmessage_context_print(FILE *fp)
             fprintf(fp, "%s: ", pgnamestr);
         }
     }
+
+    if (message_format & QMESSAGE_FORMAT_THREAD_INFO) {
+        int thid = qemu_get_thread_id();
+        const char *thname = qemu_thread_get_name();
+
+        fprintf(fp, "(%d:%s): ", thid, thname);
+    }
 }
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v3 20/20] util: add brackets around guest name in message context
  2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
                   ` (18 preceding siblings ...)
  2025-09-10 18:03 ` [PATCH v3 19/20] util: add support for formatting thread info " Daniel P. Berrangé
@ 2025-09-10 18:03 ` Daniel P. Berrangé
  2025-09-11 18:12   ` Richard Henderson
  19 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-10 18:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

The message context can optionally include the guest name if the
argument '-msg guest-name=on' is given. The formatting, however,
does not look good if the guest name contains whitespace. Change
the output to include square brackets to demarcate the name.

Before:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*' -msg guest-name=on -name "fish food"
  fish food qemu-system-x86_64(1146846:main): qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55657e94e690 dir=fish
  fish food qemu-system-x86_64(1146846:main): qcrypto_tls_creds_get_path TLS creds path creds=0x55657e94e690 filename=ca-cert.pem path=<none>
  fish food qemu-system-x86_64(1146846:main): Unable to access credentials fish/ca-cert.pem: No such file or directory

After:

  # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*' -msg guest-name=on -name "fish food"
  [fish food] qemu-system-x86_64(1144713:main): qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x5604ada2c950 dir=fish
  [fish food] qemu-system-x86_64(1144713:main): qcrypto_tls_creds_get_path TLS creds path creds=0x5604ada2c950 filename=ca-cert.pem path=<none>
  [fish food] qemu-system-x86_64(1144713:main): Unable to access credentials fish/ca-cert.pem: No such file or directory

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 util/message.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/util/message.c b/util/message.c
index 814ca0316e..7d94b9d970 100644
--- a/util/message.c
+++ b/util/message.c
@@ -28,7 +28,7 @@ void qmessage_context_print(FILE *fp)
 
     if ((message_format & QMESSAGE_FORMAT_WORKLOAD_NAME) &&
         message_workloadname) {
-        fprintf(fp, "%s ", message_workloadname);
+        fprintf(fp, "[%s] ", message_workloadname);
     }
 
     if (message_format & QMESSAGE_FORMAT_PROGRAM_NAME) {
-- 
2.50.1



^ permalink raw reply related	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
@ 2025-09-10 23:20   ` Dr. David Alan Gilbert
  2025-09-11  8:49   ` Richard Henderson
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 84+ messages in thread
From: Dr. David Alan Gilbert @ 2025-09-10 23:20 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster

* Daniel P. Berrangé (berrange@redhat.com) wrote:
> Some code makes multiple qemu_log calls to incrementally emit
> a single message. Currently timestamps get prepended to all
> qemu_log calls, even those continuing a previous incomplete
> message.
> 
> This changes the qemu_log so it skips adding a new line prefix,
> if the previous qemu_log call did NOT end with a newline.
> 
> Reported-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>

> ---
>  util/log.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/util/log.c b/util/log.c
> index abdcb6b311..2642a55c59 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
>      }
>  }
>  
> +/*
> + * 'true' if the previous log message lacked a trailing '\n',
> + * and thus the subsequent call must skip any prefix
> + */
> +static __thread bool incomplete;
> +
>  void qemu_log(const char *fmt, ...)
>  {
>      FILE *f;
> @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
>       * was emitted if we are delayed acquiring the
>       * mutex
>       */
> -    if (message_with_timestamp) {
> +    if (message_with_timestamp && !incomplete) {
>          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
>          timestr = g_date_time_format_iso8601(dt);
>      }
> @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
>          va_start(ap, fmt);
>          vfprintf(f, fmt, ap);
>          va_end(ap);
> +        incomplete = fmt[strlen(fmt) - 1] != '\n';
>          qemu_log_unlock(f);
>      }
>  }
> -- 
> 2.50.1
> 
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp()
  2025-09-10 18:03 ` [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp() Daniel P. Berrangé
@ 2025-09-11  0:08   ` Dr. David Alan Gilbert
  2025-09-11  8:51   ` Richard Henderson
  2025-09-11 17:54   ` Richard Henderson
  2 siblings, 0 replies; 84+ messages in thread
From: Dr. David Alan Gilbert @ 2025-09-11  0:08 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster

* Daniel P. Berrangé (berrange@redhat.com) wrote:
> The error_printf_unless_qmp() will print to the monitor if the current
> one is HMP, if it is QMP nothing will be printed, otherwise stderr
> will be used.
> 
> This scenario is easily handled by checking !monitor_cur_is_qmp() and
> then calling the error_printf() function.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  ui/vnc.c | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 68ca4a68e7..439d586358 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -3530,8 +3530,10 @@ int vnc_display_password(const char *id, const char *password)
>          return -EINVAL;
>      }
>      if (vd->auth == VNC_AUTH_NONE) {
> -        error_printf_unless_qmp("If you want use passwords please enable "
> -                                "password auth using '-vnc ${dpy},password'.\n");
> +        if (!monitor_cur_is_qmp()) {
> +            error_printf("If you want use passwords please enable "
> +                         "password auth using '-vnc ${dpy},password'.\n");
> +        }

OK, but while you're here, could you add the missing 'to' please.

Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>

>          return -EINVAL;
>      }
>  
> @@ -3570,9 +3572,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
>          qapi_free_SocketAddress(addr);
>          return;
>      }
> -    error_printf_unless_qmp("VNC server running on %s:%s\n",
> -                            addr->u.inet.host,
> -                            addr->u.inet.port);
> +    if (!monitor_cur_is_qmp()) {
> +        error_printf("VNC server running on %s:%s\n",
> +                     addr->u.inet.host,
> +                     addr->u.inet.port);
> +    }
>      qapi_free_SocketAddress(addr);
>  }
>  
> -- 
> 2.50.1
> 
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
  2025-09-10 23:20   ` Dr. David Alan Gilbert
@ 2025-09-11  8:49   ` Richard Henderson
  2025-09-17 14:11   ` Markus Armbruster
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11  8:49 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> Some code makes multiple qemu_log calls to incrementally emit
> a single message. Currently timestamps get prepended to all
> qemu_log calls, even those continuing a previous incomplete
> message.
> 
> This changes the qemu_log so it skips adding a new line prefix,
> if the previous qemu_log call did NOT end with a newline.
> 
> Reported-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>   util/log.c | 9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~>
> diff --git a/util/log.c b/util/log.c
> index abdcb6b311..2642a55c59 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
>       }
>   }
>   
> +/*
> + * 'true' if the previous log message lacked a trailing '\n',
> + * and thus the subsequent call must skip any prefix
> + */
> +static __thread bool incomplete;
> +
>   void qemu_log(const char *fmt, ...)
>   {
>       FILE *f;
> @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
>        * was emitted if we are delayed acquiring the
>        * mutex
>        */
> -    if (message_with_timestamp) {
> +    if (message_with_timestamp && !incomplete) {
>           g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
>           timestr = g_date_time_format_iso8601(dt);
>       }
> @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
>           va_start(ap, fmt);
>           vfprintf(f, fmt, ap);
>           va_end(ap);
> +        incomplete = fmt[strlen(fmt) - 1] != '\n';
>           qemu_log_unlock(f);
>       }
>   }



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp
  2025-09-10 18:03 ` [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp Daniel P. Berrangé
@ 2025-09-11  8:50   ` Richard Henderson
  2025-09-19 11:42   ` Markus Armbruster
  2025-09-23 12:48   ` Philippe Mathieu-Daudé
  2 siblings, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11  8:50 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> These functions only had one caller which was easily converted to
> the normal error_printf() function. Remove them as they don't add
> sufficient value.
> 
> Signed-off-by: Daniel P. Berrangé<berrange@redhat.com>
> ---
>   include/monitor/monitor.h |  3 ---
>   monitor/monitor.c         | 24 ------------------------
>   stubs/error-printf.c      |  5 -----
>   3 files changed, 32 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp()
  2025-09-10 18:03 ` [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp() Daniel P. Berrangé
  2025-09-11  0:08   ` Dr. David Alan Gilbert
@ 2025-09-11  8:51   ` Richard Henderson
  2025-09-11 17:54   ` Richard Henderson
  2 siblings, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11  8:51 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> The error_printf_unless_qmp() will print to the monitor if the current
> one is HMP, if it is QMP nothing will be printed, otherwise stderr
> will be used.
> 
> This scenario is easily handled by checking !monitor_cur_is_qmp() and
> then calling the error_printf() function.
> 
> Signed-off-by: Daniel P. Berrangé<berrange@redhat.com>
> ---
>   ui/vnc.c | 14 +++++++++-----
>   1 file changed, 9 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c
  2025-09-10 18:03 ` [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c Daniel P. Berrangé
@ 2025-09-11  8:55   ` Richard Henderson
  2025-09-19 12:27   ` Markus Armbruster
  1 sibling, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11  8:55 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> This conceptually reverts 397d30e9401d2da96dbdf0ce49805d6d4bb68833.
> The discussion around stubs in that commit does not appear to be
> important to the current state of the codebase.
> 
> This makes the error_vprintf() impl source file match that
> of error_printf(), and also match the header where it is declared.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>   monitor/monitor.c              | 13 -------------
>   stubs/monitor-core.c           |  5 +++++
>   tests/unit/test-util-sockets.c |  1 +
>   util/error-report.c            | 13 +++++++++++++
>   4 files changed, 19 insertions(+), 13 deletions(-)
> 
> diff --git a/monitor/monitor.c b/monitor/monitor.c
> index 03dbe5d131..e1e5dbfcbe 100644
> --- a/monitor/monitor.c
> +++ b/monitor/monitor.c
> @@ -268,19 +268,6 @@ void monitor_printc(Monitor *mon, int c)
>       monitor_printf(mon, "'");
>   }
>   
> -/*
> - * Print to current monitor if we have one, else to stderr.
> - */
> -int error_vprintf(const char *fmt, va_list ap)
> -{
> -    Monitor *cur_mon = monitor_cur();
> -
> -    if (cur_mon && !monitor_cur_is_qmp()) {
> -        return monitor_vprintf(cur_mon, fmt, ap);
> -    }
> -    return vfprintf(stderr, fmt, ap);
> -}
> -
>   static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
>       /* Limit guest-triggerable events to 1 per second */
>       [QAPI_EVENT_RTC_CHANGE]        = { 1000 * SCALE_MS },
> diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
> index 1894cdfe1f..b498a0f1af 100644
> --- a/stubs/monitor-core.c
> +++ b/stubs/monitor-core.c
> @@ -7,6 +7,11 @@ Monitor *monitor_cur(void)
>       return NULL;
>   }
>   
> +bool monitor_cur_is_qmp(void)
> +{
> +    return false;
> +}

Better as g_assert_not_reached().  It's not obvious whether hmp or qmp is a better 
fallback answer for "no monitor".  Anyway, since monitor_cur() is NULL, we should never 
get here.

With that,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~

> +
>   Monitor *monitor_set_cur(Coroutine *co, Monitor *mon)
>   {
>       return NULL;
> diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
> index ee66d727c3..bd48731ea2 100644
> --- a/tests/unit/test-util-sockets.c
> +++ b/tests/unit/test-util-sockets.c
> @@ -72,6 +72,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
>    * otherwise we get duplicate syms at link time.
>    */
>   Monitor *monitor_cur(void) { return cur_mon; }
> +bool monitor_cur_is_qmp(void) { return false; }
>   Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
>   int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
>   
> diff --git a/util/error-report.c b/util/error-report.c
> index 1b17c11de1..79b6f23e64 100644
> --- a/util/error-report.c
> +++ b/util/error-report.c
> @@ -29,6 +29,19 @@ bool message_with_timestamp;
>   bool error_with_guestname;
>   const char *error_guest_name;
>   
> +/*
> + * Print to current monitor if we have one, else to stderr.
> + */
> +int error_vprintf(const char *fmt, va_list ap)
> +{
> +    Monitor *cur_mon = monitor_cur();
> +
> +    if (cur_mon && !monitor_cur_is_qmp()) {
> +        return monitor_vprintf(cur_mon, fmt, ap);
> +    }
> +    return vfprintf(stderr, fmt, ap);
> +}
> +
>   int error_printf(const char *fmt, ...)
>   {
>       va_list ap;



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 03/20] system: unconditionally enable thread naming
  2025-09-10 18:03 ` [PATCH v3 03/20] system: unconditionally enable thread naming Daniel P. Berrangé
@ 2025-09-11 12:18   ` Ján Tomko
  2025-09-19  8:20   ` Markus Armbruster
  1 sibling, 0 replies; 84+ messages in thread
From: Ján Tomko @ 2025-09-11 12:18 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

[-- Attachment #1: Type: text/plain, Size: 2654 bytes --]

On a Wednesday in 2025, Daniel P. Berrangé wrote:
>When thread naming was introduced years ago, it was disabled by
>default and put behind a command line flag:
>
>  commit 8f480de0c91a18d550721f8d9af969ebfbda0793
>  Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
>  Date:   Thu Jan 30 10:20:31 2014 +0000
>
>    Add 'debug-threads' suboption to --name
>
>This was done based on a concern that something might depend
>on the historical thread naming. Thread names, however, were
>never promised to be part of QEMU's public API. The defaults
>will vary across platforms, so no assumptions should ever be
>made about naming.
>
>An opt-in behaviour is also unfortunately incompatible with
>RCU which creates its thread from an constructor function
>which is run before command line args are parsed. Thus the
>RCU thread lacks any name.
>
>libvirt has unconditionally enabled debug-threads=yes on all
>VMs it creates for 10 years. Interestingly this DID expose a
>bug in libvirt, as it parsed /proc/$PID/stat and could not
>cope with a space in the thread name. This was a latent
>pre-existing bug in libvirt though, and not a part of QEMU's
>API.
>
>Having thread names always available, will allow thread names
>to be included in error reports and log messags QEMU prints
>by default, which will improve ability to triage QEMU bugs.
>
>Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
>Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>---
> docs/about/deprecated.rst |  7 +++++++
> include/qemu/thread.h     |  1 -
> system/vl.c               | 11 ++++++-----
> util/qemu-thread-posix.c  | 18 +-----------------
> util/qemu-thread-win32.c  | 27 ++++++---------------------
> 5 files changed, 20 insertions(+), 44 deletions(-)
>
>diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
>index b2420732e1..7187ea15fa 100644
>--- a/docs/about/deprecated.rst
>+++ b/docs/about/deprecated.rst
>@@ -81,6 +81,13 @@ kernel since 2001. None of the board types QEMU supports need
> ``param_struct`` support, so this option has been deprecated and will
> be removed in a future QEMU version.
>
>+``debug-threads`` option for ``-name``

(since 10.2)

Jano

(this time on the latest version of the series, hopefully)

>+''''''''''''''''''''''''''''''''''''''
>+
>+Thread ``debug-threads`` option for the ``-name`` argument is now
>+ignored. Thread naming is unconditionally enabled for all platforms
>+where it is supported.
>+
> QEMU Machine Protocol (QMP) commands
> ------------------------------------
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name
  2025-09-10 18:03 ` [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name Daniel P. Berrangé
@ 2025-09-11 13:21   ` Christian Schoenebeck
  2025-09-12 14:58     ` Daniel P. Berrangé
  0 siblings, 1 reply; 84+ messages in thread
From: Christian Schoenebeck @ 2025-09-11 13:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Richard Henderson, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert,
	Daniel P. Berrangé

On Wednesday, September 10, 2025 8:03:42 PM CEST Daniel P. Berrangé wrote:
> This has greater portability than directly call pthread_setname_np,
> which is only 1 out of 3 possible functions for pthreads that can
> set the name.
> 
> The new API requires a trampoline function, since it can only set
> the name of the current thread.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  audio/jackaudio.c | 30 ++++++++++++++++++++++++------
>  1 file changed, 24 insertions(+), 6 deletions(-)
> 
> diff --git a/audio/jackaudio.c b/audio/jackaudio.c
> index 974a3caad3..69dce3f302 100644
> --- a/audio/jackaudio.c
> +++ b/audio/jackaudio.c
> @@ -629,18 +629,36 @@ static void qjack_enable_in(HWVoiceIn *hw, bool
> enable) ji->c.enabled = enable;
>  }
> 
> -#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> +#if !defined(WIN32)
> +struct QJackThreadData {
> +    void *(*function)(void *);
> +    void *arg;
> +};
> +
> +static void *qjack_thread_trampoline(void *targ)
> +{
> +    struct QJackThreadData *data = targ;
> +    void *(*function)(void *) = data->function;
> +    void *arg = data->arg;
> +
> +    g_free(data);
> +    qemu_thread_set_name("jack-client");
> +
> +    return function(arg);
> +}
> +
>  static int qjack_thread_creator(jack_native_thread_t *thread,
>      const pthread_attr_t *attr, void *(*function)(void *), void *arg)
>  {
> -    int ret = pthread_create(thread, attr, function, arg);
> +    struct QJackThreadData *data = g_new0(struct QJackThreadData, 1);
> +    data->function = function;
> +    data->arg = arg;
> +    int ret = pthread_create(thread, attr, qjack_thread_trampoline, data);
>      if (ret != 0) {
> +        g_free(data);
>          return ret;
>      }
> 
> -    /* set the name of the thread */
> -    pthread_setname_np(*thread, "jack-client");
> -
>      return ret;
>  }
>  #endif
> @@ -696,7 +714,7 @@ static void register_audio_jack(void)
>  {
>      qemu_mutex_init(&qjack_shutdown_lock);
>      audio_driver_register(&jack_driver);
> -#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> +#if !defined(WIN32)
>      jack_set_thread_creator(qjack_thread_creator);
>  #endif
>      jack_set_error_function(qjack_error);

Well, it does what you said, so:

Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>

I just wonder whether this thread naming code couldn't be much more simplified
now by dropping jack_set_thread_creator() entirely, which is very seldomly
used at all and had another user case [1]:

"This function can be used in very very specialized cases where it is
necessary that client threads created by JACK are created by something other
than pthread_create(). After it is used, any threads that JACK needs for the
client will will be created by calling the function passed to this function.

No normal application/client should consider calling this. The specific case
for which it was created involves running win32/x86 plugins under Wine on
Linux, where it is necessary that all threads that might call win32 functions
are known to Wine."

[1] https://jackaudio.org/api/group__ClientThreads.html#ga157ab0ade60e266ffd26ddffdb5545af

However there doesn't seem to be a thread creation callback in the JACK API,
so the jack_set_thread_creator() bypass is still the best we can get, right?

/Christian




^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-10 18:03 ` [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function Daniel P. Berrangé
@ 2025-09-11 17:52   ` Richard Henderson
  2025-09-19 12:43   ` Markus Armbruster
  1 sibling, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 17:52 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().
> 
> This is undesirable because monitor_cur_is_qmp() will itself call
> monitor_cur() again, and monitor_cur() must acquire locks and do
> hash table lookups. Introducing a monitor_cur_hmp() helper will
> combine the two operations into one reducing cost.
> 
> Signed-off-by: Daniel P. Berrangé<berrange@redhat.com>
> ---
>   include/monitor/monitor.h      |  1 +
>   monitor/monitor.c              | 14 ++++++++++++++
>   stubs/monitor-core.c           |  5 +++++
>   tests/unit/test-util-sockets.c |  1 +
>   4 files changed, 21 insertions(+)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp()
  2025-09-10 18:03 ` [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp() Daniel P. Berrangé
  2025-09-11  0:08   ` Dr. David Alan Gilbert
  2025-09-11  8:51   ` Richard Henderson
@ 2025-09-11 17:54   ` Richard Henderson
  2025-09-12 15:11     ` Daniel P. Berrangé
  2 siblings, 1 reply; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 17:54 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> The error_printf_unless_qmp() will print to the monitor if the current
> one is HMP, if it is QMP nothing will be printed, otherwise stderr
> will be used.
> 
> This scenario is easily handled by checking !monitor_cur_is_qmp() and
> then calling the error_printf() function.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>   ui/vnc.c | 14 +++++++++-----
>   1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 68ca4a68e7..439d586358 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -3530,8 +3530,10 @@ int vnc_display_password(const char *id, const char *password)
>           return -EINVAL;
>       }
>       if (vd->auth == VNC_AUTH_NONE) {
> -        error_printf_unless_qmp("If you want use passwords please enable "
> -                                "password auth using '-vnc ${dpy},password'.\n");
> +        if (!monitor_cur_is_qmp()) {
> +            error_printf("If you want use passwords please enable "
> +                         "password auth using '-vnc ${dpy},password'.\n");
> +        }
>           return -EINVAL;
>       }
>   
> @@ -3570,9 +3572,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
>           qapi_free_SocketAddress(addr);
>           return;
>       }
> -    error_printf_unless_qmp("VNC server running on %s:%s\n",
> -                            addr->u.inet.host,
> -                            addr->u.inet.port);
> +    if (!monitor_cur_is_qmp()) {
> +        error_printf("VNC server running on %s:%s\n",
> +                     addr->u.inet.host,
> +                     addr->u.inet.port);
> +    }
>       qapi_free_SocketAddress(addr);
>   }
>   

With monitor_cur_hmp, you can use monitor_printf directly.


r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 14/20] util: fix interleaving of error & trace output
  2025-09-10 18:03 ` [PATCH v3 14/20] util: fix interleaving of error & trace output Daniel P. Berrangé
@ 2025-09-11 18:01   ` Richard Henderson
  2025-09-11 18:05   ` Richard Henderson
  2025-09-22 12:16   ` Markus Armbruster
  2 siblings, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:01 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> The monitor_cur_hmp() function will acquire/release mutex locks, which
> will trigger trace probes, which can in turn trigger qemu_log() calls.
> vreport() calls monitor_cur() multiple times through its execution
> both directly and indirectly via error_vprintf().
> 
> The result is that the prefix information printed by vreport() gets
> interleaved with qemu_log() output, when run outside the context of
> an HMP command dispatcher. This can be seen with:
> 
>   $ qemu-system-x86_64
>       -msg timestamp=on,guest-name=on
>       -display none
>       -object tls-creds-x509,id=f,dir=fish
>       -name fish
>       -d trace:qemu_mutex*
>     2025-09-10T16:30:42.514374Z qemu_mutex_unlock released mutex 0x560b0339b4c0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:30:42.514400Z qemu_mutex_lock waiting on mutex 0x560b033983e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:30:42.514402Z qemu_mutex_locked taken mutex 0x560b033983e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:30:42.514404Z qemu_mutex_unlock released mutex 0x560b033983e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:30:42.516716Z qemu_mutex_lock waiting on mutex 0x560b03398560 (../monitor/monitor.c:91)
>     2025-09-10T16:30:42.516723Z qemu_mutex_locked taken mutex 0x560b03398560 (../monitor/monitor.c:91)
>     2025-09-10T16:30:42.516726Z qemu_mutex_unlock released mutex 0x560b03398560 (../monitor/monitor.c:96)
>     2025-09-10T16:30:42.516728Z qemu_mutex_lock waiting on mutex 0x560b03398560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842057Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842058Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
>     2025-09-10T16:31:04.842055Z 2025-09-10T16:31:04.842060Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842061Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842062Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
>     2025-09-10T16:31:04.842064Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842065Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842066Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
>     fish 2025-09-10T16:31:04.842068Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842069Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842070Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
>     2025-09-10T16:31:04.842072Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842097Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842099Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
>     qemu-system-x86_64:2025-09-10T16:31:04.842100Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842102Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842103Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
>      2025-09-10T16:31:04.842105Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842106Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842107Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
>     Unable to access credentials fish/ca-cert.pem: No such file or directory2025-09-10T16:31:04.842109Z qemu_mutex_lock waiting on mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842110Z qemu_mutex_locked taken mutex 0x564f5e401560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:04.842111Z qemu_mutex_unlock released mutex 0x564f5e401560 (../monitor/monitor.c:96)
> 
> To avoid this interleaving (as well as reduce the huge number of
> mutex lock/unlock calls) we need to ensure that monitor_cur_hmp() is
> only called once at the start of vreport(), and if no HMP is present,
> no further monitor APIs can be called.
> 
> This implies error_[v]printf() cannot be called from vreport().
> 
> Instead a decision about whether output will go to monitor_[v]printf()
> or fprintf() must be made upfront, and then those functions called
> directly.
> 
>   $ qemu-system-x86_64
>       -msg timestamp=on,guest-name=on
>       -display none
>       -object tls-creds-x509,id=f,dir=fish
>       -name fish
>       -d trace:qemu_mutex*
>     2025-09-10T16:31:22.701691Z qemu_mutex_unlock released mutex 0x5626fd3b84c0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:31:22.701728Z qemu_mutex_lock waiting on mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:31:22.701730Z qemu_mutex_locked taken mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:31:22.701732Z qemu_mutex_unlock released mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>     2025-09-10T16:31:22.703989Z qemu_mutex_lock waiting on mutex 0x5626fd3b5560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:22.703996Z qemu_mutex_locked taken mutex 0x5626fd3b5560 (../monitor/monitor.c:91)
>     2025-09-10T16:31:22.703999Z qemu_mutex_unlock released mutex 0x5626fd3b5560 (../monitor/monitor.c:96)
>     2025-09-10T16:31:22.704000Z fish qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> 
> This change requires adding a stub for monitor_printf() since that
> is now called directly by vreport(), where monitor_vprintf() was
> only needed previously.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>   stubs/monitor-core.c           |  5 +++
>   tests/unit/test-util-sockets.c |  1 +
>   util/error-report.c            | 60 ++++++++++++++++++++++++----------
>   3 files changed, 48 insertions(+), 18 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~

> 
> diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
> index 1e0b11ec29..70b1f7a994 100644
> --- a/stubs/monitor-core.c
> +++ b/stubs/monitor-core.c
> @@ -30,3 +30,8 @@ int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
>   {
>       abort();
>   }
> +
> +int monitor_printf(Monitor *mon, const char *fmt, ...)
> +{
> +    abort();
> +}
> diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
> index d40813c682..53733163dd 100644
> --- a/tests/unit/test-util-sockets.c
> +++ b/tests/unit/test-util-sockets.c
> @@ -76,6 +76,7 @@ Monitor *monitor_cur_hmp(void) { return cur_mon; }
>   bool monitor_cur_is_qmp(void) { return false; }
>   Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
>   int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
> +int monitor_printf(Monitor *mon, const char *fmt, ...) { abort(); }
>   
>   #ifndef _WIN32
>   static void test_socket_fd_pass_name_good(void)
> diff --git a/util/error-report.c b/util/error-report.c
> index c0fcf388de..6c887047e3 100644
> --- a/util/error-report.c
> +++ b/util/error-report.c
> @@ -29,6 +29,9 @@ bool message_with_timestamp;
>   bool error_with_guestname;
>   const char *error_guest_name;
>   
> +typedef void (*error_print_func)(void *opaque, const char *fmt, ...);
> +typedef void (*error_print_vfunc)(void *opaque, const char *fmt, va_list ap);
> +
>   /*
>    * Print to current monitor if we have one, else to stderr.
>    */
> @@ -151,34 +154,34 @@ void loc_set_file(const char *fname, int lno)
>   /*
>    * Print current location to current monitor if we have one, else to stderr.
>    */
> -static void print_loc(void)
> +static void print_loc(bool cur, error_print_func print_func, void *print_opaque)
>   {
>       const char *sep = "";
>       int i;
>       const char *const *argp;
>   
> -    if (!monitor_cur_hmp() && g_get_prgname()) {
> -        error_printf("%s:", g_get_prgname());
> +    if (!cur && g_get_prgname()) {
> +        print_func(print_opaque, "%s:", g_get_prgname());
>           sep = " ";
>       }
>       switch (cur_loc->kind) {
>       case LOC_CMDLINE:
>           argp = cur_loc->ptr;
>           for (i = 0; i < cur_loc->num; i++) {
> -            error_printf("%s%s", sep, argp[i]);
> +            print_func(print_opaque, "%s%s", sep, argp[i]);
>               sep = " ";
>           }
> -        error_printf(": ");
> +        print_func(print_opaque, ": ");
>           break;
>       case LOC_FILE:
> -        error_printf("%s:", (const char *)cur_loc->ptr);
> +        print_func(print_opaque, "%s:", (const char *)cur_loc->ptr);
>           if (cur_loc->num) {
> -            error_printf("%d:", cur_loc->num);
> +            print_func(print_opaque, "%d:", cur_loc->num);
>           }
> -        error_printf(" ");
> +        print_func(print_opaque, " ");
>           break;
>       default:
> -        error_printf("%s", sep);
> +        print_func(print_opaque, "%s", sep);
>       }
>   }
>   
> @@ -199,34 +202,55 @@ real_time_iso8601(void)
>   G_GNUC_PRINTF(2, 0)
>   static void vreport(report_type type, const char *fmt, va_list ap)
>   {
> +    /*
> +     * Calling monitor_cur_hmp() will acquire/release mutexes,
> +     * which triggers trace probes, which can trigger
> +     * qemu_log calls, which would interleave with output
> +     * from this. Hence cache the monitor handle upfront
> +     * so any tracing appears before we start outputting.
> +     */
> +    Monitor *cur = monitor_cur_hmp();
> +    error_print_func print_func;
> +    error_print_vfunc print_vfunc;
> +    void *print_opaque;
>       gchar *timestr;
>   
> -    if (message_with_timestamp && !monitor_cur_hmp()) {
> +    if (cur) {
> +        print_func = (error_print_func)monitor_printf;
> +        print_vfunc = (error_print_vfunc)monitor_vprintf;
> +        print_opaque = cur;
> +    } else {
> +        print_func = (error_print_func)fprintf;
> +        print_vfunc = (error_print_vfunc)vfprintf;
> +        print_opaque = stderr;
> +    }
> +
> +    if (message_with_timestamp && !cur) {
>           timestr = real_time_iso8601();
> -        error_printf("%s ", timestr);
> +        print_func(print_opaque, "%s ", timestr);
>           g_free(timestr);
>       }
>   
>       /* Only prepend guest name if -msg guest-name and -name guest=... are set */
> -    if (error_with_guestname && error_guest_name && !monitor_cur_hmp()) {
> -        error_printf("%s ", error_guest_name);
> +    if (error_with_guestname && error_guest_name && !cur) {
> +        print_func(print_opaque, "%s ", error_guest_name);
>       }
>   
> -    print_loc();
> +    print_loc(!!cur, print_func, print_opaque);
>   
>       switch (type) {
>       case REPORT_TYPE_ERROR:
>           break;
>       case REPORT_TYPE_WARNING:
> -        error_printf("warning: ");
> +        print_func(print_opaque, "warning: ");
>           break;
>       case REPORT_TYPE_INFO:
> -        error_printf("info: ");
> +        print_func(print_opaque, "info: ");
>           break;
>       }
>   
> -    error_vprintf(fmt, ap);
> -    error_printf("\n");
> +    print_vfunc(print_opaque, fmt, ap);
> +    print_func(print_opaque, "\n");
>   }
>   
>   /*



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 15/20] util: introduce common helper for error-report & log code
  2025-09-10 18:03 ` [PATCH v3 15/20] util: introduce common helper for error-report & log code Daniel P. Berrangé
@ 2025-09-11 18:02   ` Richard Henderson
  0 siblings, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:02 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> +void qmessage_context_print(FILE *fp)
> +{
> +
> +    if (message_format & QMESSAGE_FORMAT_TIMESTAMP) {

Extra vertical whitespace.  Otherwise,

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 16/20] util: convert error-report & log to message API for timestamp
  2025-09-10 18:03 ` [PATCH v3 16/20] util: convert error-report & log to message API for timestamp Daniel P. Berrangé
@ 2025-09-11 18:04   ` Richard Henderson
  0 siblings, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:04 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> Both the error-report and log APIs can optional emit a timestamp
> as a prefix on messages, with the '-msg timestamp=on' command
> line flag is set.
> 
> Convert them to the new message API for formatting the context
> prefix, guaranteeing they will have matching behaviour going
> forward.
> 
> There is no change in output format for either logs or errors
> with this conversion.
> 
> Signed-off-by: Daniel P. Berrangé<berrange@redhat.com>
> ---
>   include/qemu/error-report.h    |  1 -
>   system/vl.c                    |  7 ++++++-
>   tests/unit/test-error-report.c |  3 ++-
>   util/error-report.c            | 17 ++---------------
>   util/log.c                     | 21 ++++-----------------
>   5 files changed, 14 insertions(+), 35 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 14/20] util: fix interleaving of error & trace output
  2025-09-10 18:03 ` [PATCH v3 14/20] util: fix interleaving of error & trace output Daniel P. Berrangé
  2025-09-11 18:01   ` Richard Henderson
@ 2025-09-11 18:05   ` Richard Henderson
  2025-09-12 16:30     ` Daniel P. Berrangé
  2025-09-22 12:16   ` Markus Armbruster
  2 siblings, 1 reply; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:05 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> +    } else {
> +        print_func = (error_print_func)fprintf;
> +        print_vfunc = (error_print_vfunc)vfprintf;
> +        print_opaque = stderr;
> +    }
> +
> +    if (message_with_timestamp && !cur) {
>           timestr = real_time_iso8601();
> -        error_printf("%s ", timestr);
> +        print_func(print_opaque, "%s ", timestr);
>           g_free(timestr);
>       }
>   
>       /* Only prepend guest name if -msg guest-name and -name guest=... are set */
> -    if (error_with_guestname && error_guest_name && !monitor_cur_hmp()) {
> -        error_printf("%s ", error_guest_name);
> +    if (error_with_guestname && error_guest_name && !cur) {
> +        print_func(print_opaque, "%s ", error_guest_name);
>       }

It's worth pushing these second and third if into the first else,
so that !cur is already true.


r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 17/20] util: add support for formatting a workload name in messages
  2025-09-10 18:03 ` [PATCH v3 17/20] util: add support for formatting a workload name in messages Daniel P. Berrangé
@ 2025-09-11 18:06   ` Richard Henderson
  2025-09-11 20:27   ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:06 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> The error_report function can include the guest name in any
> messages it prints. The qemu_log function has no equivalent
> behaviour.
> 
> This introduces support for a "workload name" in the new
> messages API, which in the case of system emulators will
> be the guest name. The possibility of defining a workload
> name for other binaries is left as an exercise for the
> future.
> 
> This change has no impact on the output of the error_report
> function, but will change the qemu_log function. This can
> be easily seen with the 'log' trace backend, and how it is
> now more closely matching error_report output.
> 
> Before:
> 
>    # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
>    qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
>    qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
>    blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> 
> After:
> 
>    # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
>    blah qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
>    blah qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
>    blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> 
> Signed-off-by: Daniel P. Berrangé<berrange@redhat.com>
> ---
>   include/qemu/error-report.h |  3 ---
>   include/qemu/message.h      | 10 ++++++++++
>   system/vl.c                 |  6 ++++--
>   util/error-report.c         |  7 -------
>   util/message.c              | 12 +++++++++++-
>   5 files changed, 25 insertions(+), 13 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 18/20] util: add support for formatting a program name in messages
  2025-09-10 18:03 ` [PATCH v3 18/20] util: add support for formatting a program " Daniel P. Berrangé
@ 2025-09-11 18:07   ` Richard Henderson
  2025-09-11 18:08     ` Richard Henderson
  2025-09-12 16:33     ` Daniel P. Berrangé
  0 siblings, 2 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:07 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> @@ -157,10 +157,6 @@ static void print_loc(bool cur, error_print_func print_func, void *print_opaque)
>       int i;
>       const char *const *argp;
>   
> -    if (!cur && g_get_prgname()) {
> -        print_func(print_opaque, "%s:", g_get_prgname());
> -        sep = " ";
> -    }

Last use of cur in this function is removed.


r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 18/20] util: add support for formatting a program name in messages
  2025-09-11 18:07   ` Richard Henderson
@ 2025-09-11 18:08     ` Richard Henderson
  2025-09-12 16:33     ` Daniel P. Berrangé
  1 sibling, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:08 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/11/25 18:07, Richard Henderson wrote:
> On 9/10/25 18:03, Daniel P. Berrangé wrote:
>> @@ -157,10 +157,6 @@ static void print_loc(bool cur, error_print_func print_func, void 
>> *print_opaque)
>>       int i;
>>       const char *const *argp;
>> -    if (!cur && g_get_prgname()) {
>> -        print_func(print_opaque, "%s:", g_get_prgname());
>> -        sep = " ";
>> -    }
> 
> Last use of cur in this function is removed.

Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 19/20] util: add support for formatting thread info in messages
  2025-09-10 18:03 ` [PATCH v3 19/20] util: add support for formatting thread info " Daniel P. Berrangé
@ 2025-09-11 18:11   ` Richard Henderson
  2025-09-12  8:36     ` Daniel P. Berrangé
  0 siblings, 1 reply; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:11 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> --- a/storage-daemon/qemu-storage-daemon.c
> +++ b/storage-daemon/qemu-storage-daemon.c
> @@ -47,6 +47,7 @@
>   #include "qemu/cutils.h"
>   #include "qemu/config-file.h"
>   #include "qemu/error-report.h"
> +#include "qemu/message.h"
>   #include "qemu/help_option.h"
>   #include "qemu/job.h"
>   #include "qemu/log.h"
> @@ -65,6 +66,10 @@ static const char *pid_file;
>   static char *pid_file_realpath;
>   static volatile bool exit_requested = false;
>   
> +#define QMESSAGE_FORMAT_DEFAULT \
> +    (QMESSAGE_FORMAT_PROGRAM_NAME | \
> +     QMESSAGE_FORMAT_THREAD_INFO)
> +
>   void qemu_system_killed(int signal, pid_t pid)
>   {
>       exit_requested = true;
> @@ -399,6 +404,7 @@ int main(int argc, char *argv[])
>   #endif
>   
>       error_init(argv[0]);
> +    qmessage_set_format(QMESSAGE_FORMAT_DEFAULT);
>       qemu_init_exec_dir(argv[0]);
>       os_setup_signal_handling();
>   
> diff --git a/system/vl.c b/system/vl.c
> index 9030212c50..20b655a7bc 100644
> --- a/system/vl.c
> +++ b/system/vl.c
> @@ -145,6 +145,10 @@
>   
>   #define MAX_VIRTIO_CONSOLES 1
>   
> +#define QMESSAGE_FORMAT_DEFAULT \
> +    (QMESSAGE_FORMAT_PROGRAM_NAME | \
> +     QMESSAGE_FORMAT_THREAD_INFO)
> +
>   typedef struct BlockdevOptionsQueueEntry {
>       BlockdevOptions *bdo;
>       Location loc;
> @@ -811,10 +815,9 @@ static void realtime_init(void)
>       }
>   }
>   
> -
>   static void configure_msg(QemuOpts *opts)
>   {
> -    int flags = QMESSAGE_FORMAT_PROGRAM_NAME;
> +    int flags = QMESSAGE_FORMAT_DEFAULT;
>       if (qemu_opt_get_bool(opts, "timestamp", false)) {
>           flags |= QMESSAGE_FORMAT_TIMESTAMP;
>       }
> @@ -2888,6 +2891,7 @@ void qemu_init(int argc, char **argv)
>       module_call_init(MODULE_INIT_OPTS);
>   
>       error_init(argv[0]);
> +    qmessage_set_format(QMESSAGE_FORMAT_DEFAULT);

Worth a static initial value of the variable, rather than require two other startup calls?

This also seems like it should be a separate patch from adding THREAD_INFO to 
qmessage_context_print.


r~


>       qemu_init_exec_dir(argv[0]);
>   
>       os_setup_limits();
> diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
> index 8452845f44..dc2666afe7 100755
> --- a/tests/qemu-iotests/041
> +++ b/tests/qemu-iotests/041
> @@ -1102,7 +1102,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
>           self.vm.shutdown()
>           log = iotests.filter_qtest(self.vm.get_log())
>           log = re.sub(r'^Formatting.*\n', '', log)
> -        log = re.sub(r'^%s: ' % os.path.basename(iotests.qemu_prog), '', log)
> +        log = re.sub(r'^%s: \(\d+:\w+\): ' % os.path.basename(iotests.qemu_prog), '', log)
>   
>           self.assertEqual(log,
>                            "Can no longer replace 'img1' by 'repair0', because " +
> diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
> index 511a55b1e8..84f352d30b 100644
> --- a/tests/qemu-iotests/common.filter
> +++ b/tests/qemu-iotests/common.filter
> @@ -81,7 +81,7 @@ _filter_qemu_io()
>   # replace occurrences of QEMU_PROG with "qemu"
>   _filter_qemu()
>   {
> -    gsed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" \
> +    gsed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG): ([0-9]\+:[-_a-zA-Z]\+):#\1QEMU_PROG:#" \
>           -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#' \
>           -e $'s#\r##' # QEMU monitor uses \r\n line endings
>   }
> diff --git a/util/message.c b/util/message.c
> index 1db9254733..814ca0316e 100644
> --- a/util/message.c
> +++ b/util/message.c
> @@ -37,4 +37,11 @@ void qmessage_context_print(FILE *fp)
>               fprintf(fp, "%s: ", pgnamestr);
>           }
>       }
> +
> +    if (message_format & QMESSAGE_FORMAT_THREAD_INFO) {
> +        int thid = qemu_get_thread_id();
> +        const char *thname = qemu_thread_get_name();
> +
> +        fprintf(fp, "(%d:%s): ", thid, thname);
> +    }
>   }



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 20/20] util: add brackets around guest name in message context
  2025-09-10 18:03 ` [PATCH v3 20/20] util: add brackets around guest name in message context Daniel P. Berrangé
@ 2025-09-11 18:12   ` Richard Henderson
  0 siblings, 0 replies; 84+ messages in thread
From: Richard Henderson @ 2025-09-11 18:12 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On 9/10/25 18:03, Daniel P. Berrangé wrote:
> The message context can optionally include the guest name if the
> argument '-msg guest-name=on' is given. The formatting, however,
> does not look good if the guest name contains whitespace. Change
> the output to include square brackets to demarcate the name.
> 
> Before:
> 
>    # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*' -msg guest-name=on -name "fish food"
>    fish food qemu-system-x86_64(1146846:main): qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55657e94e690 dir=fish
>    fish food qemu-system-x86_64(1146846:main): qcrypto_tls_creds_get_path TLS creds path creds=0x55657e94e690 filename=ca-cert.pem path=<none>
>    fish food qemu-system-x86_64(1146846:main): Unable to access credentials fish/ca-cert.pem: No such file or directory
> 
> After:
> 
>    # qemu-system-x86_64 -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*' -msg guest-name=on -name "fish food"
>    [fish food] qemu-system-x86_64(1144713:main): qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x5604ada2c950 dir=fish
>    [fish food] qemu-system-x86_64(1144713:main): qcrypto_tls_creds_get_path TLS creds path creds=0x5604ada2c950 filename=ca-cert.pem path=<none>
>    [fish food] qemu-system-x86_64(1144713:main): Unable to access credentials fish/ca-cert.pem: No such file or directory
> 
> Signed-off-by: Daniel P. Berrangé<berrange@redhat.com>
> ---
>   util/message.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 17/20] util: add support for formatting a workload name in messages
  2025-09-10 18:03 ` [PATCH v3 17/20] util: add support for formatting a workload name in messages Daniel P. Berrangé
  2025-09-11 18:06   ` Richard Henderson
@ 2025-09-11 20:27   ` Dr. David Alan Gilbert
  2025-09-12  8:34     ` Daniel P. Berrangé
  1 sibling, 1 reply; 84+ messages in thread
From: Dr. David Alan Gilbert @ 2025-09-11 20:27 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster

* Daniel P. Berrangé (berrange@redhat.com) wrote:
> The error_report function can include the guest name in any
> messages it prints. The qemu_log function has no equivalent
> behaviour.
> 
> This introduces support for a "workload name" in the new
> messages API, which in the case of system emulators will
> be the guest name. The possibility of defining a workload
> name for other binaries is left as an exercise for the
> future.
> 
> This change has no impact on the output of the error_report
> function, but will change the qemu_log function. This can
> be easily seen with the 'log' trace backend, and how it is
> now more closely matching error_report output.
> 
> Before:
> 
>   # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
>   qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
>   qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
>   blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> 
> After:
> 
>   # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
>   blah qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
>   blah qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
>   blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

Are you going to want to escape that? I see later you're adding []'s around it,
which makes it feel like you want to end up with it parsable, but if some nasty
person does:

-name ']})🐧({['

then things get confusing; I guess you're hoping that whoever calls qemu will
be careful not to allow that.

Dave

> ---
>  include/qemu/error-report.h |  3 ---
>  include/qemu/message.h      | 10 ++++++++++
>  system/vl.c                 |  6 ++++--
>  util/error-report.c         |  7 -------
>  util/message.c              | 12 +++++++++++-
>  5 files changed, 25 insertions(+), 13 deletions(-)
> 
> diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h
> index c8000778ec..ffc305f828 100644
> --- a/include/qemu/error-report.h
> +++ b/include/qemu/error-report.h
> @@ -70,7 +70,4 @@ void error_init(const char *argv0);
>                                fmt, ##__VA_ARGS__);      \
>      })
>  
> -extern bool error_with_guestname;
> -extern const char *error_guest_name;
> -
>  #endif
> diff --git a/include/qemu/message.h b/include/qemu/message.h
> index 0a06421f77..cfc3c92648 100644
> --- a/include/qemu/message.h
> +++ b/include/qemu/message.h
> @@ -5,6 +5,7 @@
>  
>  enum QMessageFormatFlags {
>      QMESSAGE_FORMAT_TIMESTAMP = (1 << 0),
> +    QMESSAGE_FORMAT_WORKLOAD_NAME = (1 << 1),
>  };
>  
>  /**
> @@ -16,6 +17,15 @@ enum QMessageFormatFlags {
>   */
>  void qmessage_set_format(int flags);
>  
> +/**
> + * qmessage_set_workload_name:
> + * @name: the name of the workload
> + *
> + * Set the workload name, which for a system emulator
> + * will be the guest VM name.
> + */
> +void qmessage_set_workload_name(const char *name);
> +
>  /**
>   * qmessage_context_print:
>   * @fp: file to emit the prefix on
> diff --git a/system/vl.c b/system/vl.c
> index 696dd92669..fee6fdf7b1 100644
> --- a/system/vl.c
> +++ b/system/vl.c
> @@ -818,7 +818,9 @@ static void configure_msg(QemuOpts *opts)
>      if (qemu_opt_get_bool(opts, "timestamp", false)) {
>          flags |= QMESSAGE_FORMAT_TIMESTAMP;
>      }
> -    error_with_guestname = qemu_opt_get_bool(opts, "guest-name", false);
> +    if (qemu_opt_get_bool(opts, "guest-name", false)) {
> +        flags |= QMESSAGE_FORMAT_WORKLOAD_NAME;
> +    }
>      qmessage_set_format(flags);
>  }
>  
> @@ -3520,7 +3522,7 @@ void qemu_init(int argc, char **argv)
>                      exit(1);
>                  }
>                  /* Capture guest name if -msg guest-name is used later */
> -                error_guest_name = qemu_opt_get(opts, "guest");
> +                qmessage_set_workload_name(qemu_opt_get(opts, "guest"));
>                  break;
>              case QEMU_OPTION_prom_env:
>                  if (nb_prom_envs >= MAX_PROM_ENVS) {
> diff --git a/util/error-report.c b/util/error-report.c
> index 719f059494..c40cdf3bb3 100644
> --- a/util/error-report.c
> +++ b/util/error-report.c
> @@ -25,8 +25,6 @@ typedef enum {
>      REPORT_TYPE_INFO,
>  } report_type;
>  
> -bool error_with_guestname;
> -const char *error_guest_name;
>  
>  typedef void (*error_print_func)(void *opaque, const char *fmt, ...);
>  typedef void (*error_print_vfunc)(void *opaque, const char *fmt, va_list ap);
> @@ -218,11 +216,6 @@ static void vreport(report_type type, const char *fmt, va_list ap)
>          qmessage_context_print(stderr);
>      }
>  
> -    /* Only prepend guest name if -msg guest-name and -name guest=... are set */
> -    if (error_with_guestname && error_guest_name && !cur) {
> -        print_func(print_opaque, "%s ", error_guest_name);
> -    }
> -
>      print_loc(!!cur, print_func, print_opaque);
>  
>      switch (type) {
> diff --git a/util/message.c b/util/message.c
> index ef70e08c5f..a91c008e08 100644
> --- a/util/message.c
> +++ b/util/message.c
> @@ -6,18 +6,28 @@
>  #include "monitor/monitor.h"
>  
>  static int message_format;
> +static char *message_workloadname;
>  
>  void qmessage_set_format(int flags)
>  {
>      message_format = flags;
>  }
>  
> -void qmessage_context_print(FILE *fp)
> +void qmessage_set_workload_name(const char *name)
>  {
> +    message_workloadname = g_strdup(name);
> +}
>  
> +void qmessage_context_print(FILE *fp)
> +{
>      if (message_format & QMESSAGE_FORMAT_TIMESTAMP) {
>          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
>          g_autofree char *timestr = g_date_time_format_iso8601(dt);
>          fprintf(fp, "%s ", timestr);
>      }
> +
> +    if ((message_format & QMESSAGE_FORMAT_WORKLOAD_NAME) &&
> +        message_workloadname) {
> +        fprintf(fp, "%s ", message_workloadname);
> +    }
>  }
> -- 
> 2.50.1
> 
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 17/20] util: add support for formatting a workload name in messages
  2025-09-11 20:27   ` Dr. David Alan Gilbert
@ 2025-09-12  8:34     ` Daniel P. Berrangé
  2025-09-12 11:18       ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12  8:34 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster

On Thu, Sep 11, 2025 at 08:27:36PM +0000, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrangé (berrange@redhat.com) wrote:
> > The error_report function can include the guest name in any
> > messages it prints. The qemu_log function has no equivalent
> > behaviour.
> > 
> > This introduces support for a "workload name" in the new
> > messages API, which in the case of system emulators will
> > be the guest name. The possibility of defining a workload
> > name for other binaries is left as an exercise for the
> > future.
> > 
> > This change has no impact on the output of the error_report
> > function, but will change the qemu_log function. This can
> > be easily seen with the 'log' trace backend, and how it is
> > now more closely matching error_report output.
> > 
> > Before:
> > 
> >   # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
> >   qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
> >   qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
> >   blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> > 
> > After:
> > 
> >   # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
> >   blah qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
> >   blah qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
> >   blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> > 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> 
> Are you going to want to escape that? I see later you're adding []'s around it,
> which makes it feel like you want to end up with it parsable, but if some nasty
> person does:
> 
> -name ']})🐧({['
> 
> then things get confusing; I guess you're hoping that whoever calls qemu will
> be careful not to allow that.

I was considering the log output to be human targetted, rather
than something to be parsed. IOW, if users want to confuse
themselves with wierd names, that's their own (unwise) decision.

If we added ecaping of the name, it'd probably even more difficult
to read for a human, even if we make it a bit easier for humans ?

TL;DR: do we care about parseability here, or just humans reading ?

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 19/20] util: add support for formatting thread info in messages
  2025-09-11 18:11   ` Richard Henderson
@ 2025-09-12  8:36     ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12  8:36 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

On Thu, Sep 11, 2025 at 06:11:47PM +0000, Richard Henderson wrote:
> On 9/10/25 18:03, Daniel P. Berrangé wrote:
> > --- a/storage-daemon/qemu-storage-daemon.c
> > +++ b/storage-daemon/qemu-storage-daemon.c
> > @@ -47,6 +47,7 @@
> >   #include "qemu/cutils.h"
> >   #include "qemu/config-file.h"
> >   #include "qemu/error-report.h"
> > +#include "qemu/message.h"
> >   #include "qemu/help_option.h"
> >   #include "qemu/job.h"
> >   #include "qemu/log.h"
> > @@ -65,6 +66,10 @@ static const char *pid_file;
> >   static char *pid_file_realpath;
> >   static volatile bool exit_requested = false;
> > +#define QMESSAGE_FORMAT_DEFAULT \
> > +    (QMESSAGE_FORMAT_PROGRAM_NAME | \
> > +     QMESSAGE_FORMAT_THREAD_INFO)
> > +
> >   void qemu_system_killed(int signal, pid_t pid)
> >   {
> >       exit_requested = true;
> > @@ -399,6 +404,7 @@ int main(int argc, char *argv[])
> >   #endif
> >       error_init(argv[0]);
> > +    qmessage_set_format(QMESSAGE_FORMAT_DEFAULT);
> >       qemu_init_exec_dir(argv[0]);
> >       os_setup_signal_handling();
> > diff --git a/system/vl.c b/system/vl.c
> > index 9030212c50..20b655a7bc 100644
> > --- a/system/vl.c
> > +++ b/system/vl.c
> > @@ -145,6 +145,10 @@
> >   #define MAX_VIRTIO_CONSOLES 1
> > +#define QMESSAGE_FORMAT_DEFAULT \
> > +    (QMESSAGE_FORMAT_PROGRAM_NAME | \
> > +     QMESSAGE_FORMAT_THREAD_INFO)
> > +
> >   typedef struct BlockdevOptionsQueueEntry {
> >       BlockdevOptions *bdo;
> >       Location loc;
> > @@ -811,10 +815,9 @@ static void realtime_init(void)
> >       }
> >   }
> > -
> >   static void configure_msg(QemuOpts *opts)
> >   {
> > -    int flags = QMESSAGE_FORMAT_PROGRAM_NAME;
> > +    int flags = QMESSAGE_FORMAT_DEFAULT;
> >       if (qemu_opt_get_bool(opts, "timestamp", false)) {
> >           flags |= QMESSAGE_FORMAT_TIMESTAMP;
> >       }
> > @@ -2888,6 +2891,7 @@ void qemu_init(int argc, char **argv)
> >       module_call_init(MODULE_INIT_OPTS);
> >       error_init(argv[0]);
> > +    qmessage_set_format(QMESSAGE_FORMAT_DEFAULT);
> 
> Worth a static initial value of the variable, rather than require two other startup calls?

NB, the qmessage stuff is linked into all our other binaries too,
and so I only wanted to turn on thread info for the subset of
binaries that are likely to be using multiple threads. Then
again, posibly both qemu-nbd and qemu-img might use threads
in some scenarios

> This also seems like it should be a separate patch from adding THREAD_INFO
> to qmessage_context_print.

Sure, I can do that.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 17/20] util: add support for formatting a workload name in messages
  2025-09-12  8:34     ` Daniel P. Berrangé
@ 2025-09-12 11:18       ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 84+ messages in thread
From: Dr. David Alan Gilbert @ 2025-09-12 11:18 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster

* Daniel P. Berrangé (berrange@redhat.com) wrote:
> On Thu, Sep 11, 2025 at 08:27:36PM +0000, Dr. David Alan Gilbert wrote:
> > * Daniel P. Berrangé (berrange@redhat.com) wrote:
> > > The error_report function can include the guest name in any
> > > messages it prints. The qemu_log function has no equivalent
> > > behaviour.
> > > 
> > > This introduces support for a "workload name" in the new
> > > messages API, which in the case of system emulators will
> > > be the guest name. The possibility of defining a workload
> > > name for other binaries is left as an exercise for the
> > > future.
> > > 
> > > This change has no impact on the output of the error_report
> > > function, but will change the qemu_log function. This can
> > > be easily seen with the 'log' trace backend, and how it is
> > > now more closely matching error_report output.
> > > 
> > > Before:
> > > 
> > >   # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
> > >   qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
> > >   qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
> > >   blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> > > 
> > > After:
> > > 
> > >   # qemu-system-x86_64 -msg guest-name=on -name blah -object tls-creds-x509,id=t0,dir=fish -d 'trace:qcrypto*'
> > >   blah qcrypto_tls_creds_x509_load TLS creds x509 load creds=0x55b3af3fd870 dir=fish
> > >   blah qcrypto_tls_creds_get_path TLS creds path creds=0x55b3af3fd870 filename=ca-cert.pem path=<none>
> > >   blah qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
> > > 
> > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > 
> > Are you going to want to escape that? I see later you're adding []'s around it,
> > which makes it feel like you want to end up with it parsable, but if some nasty
> > person does:
> > 
> > -name ']})🐧({['
> > 
> > then things get confusing; I guess you're hoping that whoever calls qemu will
> > be careful not to allow that.
> 
> I was considering the log output to be human targetted, rather
> than something to be parsed. IOW, if users want to confuse
> themselves with wierd names, that's their own (unwise) decision.
> 
> If we added ecaping of the name, it'd probably even more difficult
> to read for a human, even if we make it a bit easier for humans ?
> 
> TL;DR: do we care about parseability here, or just humans reading ?

If it's just humans that's fine; if anywhere were documenting the output
format then it should probably have a warning.

Dave

> With regards,
> Daniel
> -- 
> |: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org         -o-            https://fstop138.berrange.com :|
> |: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
> 
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name
  2025-09-11 13:21   ` Christian Schoenebeck
@ 2025-09-12 14:58     ` Daniel P. Berrangé
  2025-09-19  8:46       ` Markus Armbruster
  0 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 14:58 UTC (permalink / raw)
  To: Christian Schoenebeck
  Cc: qemu-devel, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Richard Henderson, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini,
	Markus Armbruster, Dr. David Alan Gilbert

On Thu, Sep 11, 2025 at 03:21:04PM +0200, Christian Schoenebeck wrote:
> On Wednesday, September 10, 2025 8:03:42 PM CEST Daniel P. Berrangé wrote:
> > This has greater portability than directly call pthread_setname_np,
> > which is only 1 out of 3 possible functions for pthreads that can
> > set the name.
> > 
> > The new API requires a trampoline function, since it can only set
> > the name of the current thread.
> > 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  audio/jackaudio.c | 30 ++++++++++++++++++++++++------
> >  1 file changed, 24 insertions(+), 6 deletions(-)
> > 
> > diff --git a/audio/jackaudio.c b/audio/jackaudio.c
> > index 974a3caad3..69dce3f302 100644
> > --- a/audio/jackaudio.c
> > +++ b/audio/jackaudio.c
> > @@ -629,18 +629,36 @@ static void qjack_enable_in(HWVoiceIn *hw, bool
> > enable) ji->c.enabled = enable;
> >  }
> > 
> > -#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> > +#if !defined(WIN32)
> > +struct QJackThreadData {
> > +    void *(*function)(void *);
> > +    void *arg;
> > +};
> > +
> > +static void *qjack_thread_trampoline(void *targ)
> > +{
> > +    struct QJackThreadData *data = targ;
> > +    void *(*function)(void *) = data->function;
> > +    void *arg = data->arg;
> > +
> > +    g_free(data);
> > +    qemu_thread_set_name("jack-client");
> > +
> > +    return function(arg);
> > +}
> > +
> >  static int qjack_thread_creator(jack_native_thread_t *thread,
> >      const pthread_attr_t *attr, void *(*function)(void *), void *arg)
> >  {
> > -    int ret = pthread_create(thread, attr, function, arg);
> > +    struct QJackThreadData *data = g_new0(struct QJackThreadData, 1);
> > +    data->function = function;
> > +    data->arg = arg;
> > +    int ret = pthread_create(thread, attr, qjack_thread_trampoline, data);
> >      if (ret != 0) {
> > +        g_free(data);
> >          return ret;
> >      }
> > 
> > -    /* set the name of the thread */
> > -    pthread_setname_np(*thread, "jack-client");
> > -
> >      return ret;
> >  }
> >  #endif
> > @@ -696,7 +714,7 @@ static void register_audio_jack(void)
> >  {
> >      qemu_mutex_init(&qjack_shutdown_lock);
> >      audio_driver_register(&jack_driver);
> > -#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> > +#if !defined(WIN32)
> >      jack_set_thread_creator(qjack_thread_creator);
> >  #endif
> >      jack_set_error_function(qjack_error);
> 
> Well, it does what you said, so:
> 
> Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> 
> I just wonder whether this thread naming code couldn't be much more simplified
> now by dropping jack_set_thread_creator() entirely, which is very seldomly
> used at all and had another user case [1]:
> 
> "This function can be used in very very specialized cases where it is
> necessary that client threads created by JACK are created by something other
> than pthread_create(). After it is used, any threads that JACK needs for the
> client will will be created by calling the function passed to this function.
> 
> No normal application/client should consider calling this. The specific case
> for which it was created involves running win32/x86 plugins under Wine on
> Linux, where it is necessary that all threads that might call win32 functions
> are known to Wine."
> 
> [1] https://jackaudio.org/api/group__ClientThreads.html#ga157ab0ade60e266ffd26ddffdb5545af
> 
> However there doesn't seem to be a thread creation callback in the JACK API,
> so the jack_set_thread_creator() bypass is still the best we can get, right?

From QEMU's POV the only value we get from using the thread callback
is that we can set the thread name so the jack thrread can be easily
identified when debugging.  I don't think there's another easy way
to get that set, as we can't portability set thread names from outside
the thread.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp()
  2025-09-11 17:54   ` Richard Henderson
@ 2025-09-12 15:11     ` Daniel P. Berrangé
  2025-09-19 11:42       ` Markus Armbruster
  0 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 15:11 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

On Thu, Sep 11, 2025 at 05:54:48PM +0000, Richard Henderson wrote:
> On 9/10/25 18:03, Daniel P. Berrangé wrote:
> > The error_printf_unless_qmp() will print to the monitor if the current
> > one is HMP, if it is QMP nothing will be printed, otherwise stderr
> > will be used.
> > 
> > This scenario is easily handled by checking !monitor_cur_is_qmp() and
> > then calling the error_printf() function.
> > 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >   ui/vnc.c | 14 +++++++++-----
> >   1 file changed, 9 insertions(+), 5 deletions(-)
> > 
> > diff --git a/ui/vnc.c b/ui/vnc.c
> > index 68ca4a68e7..439d586358 100644
> > --- a/ui/vnc.c
> > +++ b/ui/vnc.c
> > @@ -3530,8 +3530,10 @@ int vnc_display_password(const char *id, const char *password)
> >           return -EINVAL;
> >       }
> >       if (vd->auth == VNC_AUTH_NONE) {
> > -        error_printf_unless_qmp("If you want use passwords please enable "
> > -                                "password auth using '-vnc ${dpy},password'.\n");
> > +        if (!monitor_cur_is_qmp()) {
> > +            error_printf("If you want use passwords please enable "
> > +                         "password auth using '-vnc ${dpy},password'.\n");
> > +        }
> >           return -EINVAL;
> >       }
> > @@ -3570,9 +3572,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
> >           qapi_free_SocketAddress(addr);
> >           return;
> >       }
> > -    error_printf_unless_qmp("VNC server running on %s:%s\n",
> > -                            addr->u.inet.host,
> > -                            addr->u.inet.port);
> > +    if (!monitor_cur_is_qmp()) {
> > +        error_printf("VNC server running on %s:%s\n",
> > +                     addr->u.inet.host,
> > +                     addr->u.inet.port);
> > +    }
> >       qapi_free_SocketAddress(addr);
> >   }
> 
> With monitor_cur_hmp, you can use monitor_printf directly.

We still need to be able to print to stderr when there is neither HMP
nor QMP, which error_printf gets us, but monitor_printf would not.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 14/20] util: fix interleaving of error & trace output
  2025-09-11 18:05   ` Richard Henderson
@ 2025-09-12 16:30     ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 16:30 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

On Thu, Sep 11, 2025 at 06:05:01PM +0000, Richard Henderson wrote:
> On 9/10/25 18:03, Daniel P. Berrangé wrote:
> > +    } else {
> > +        print_func = (error_print_func)fprintf;
> > +        print_vfunc = (error_print_vfunc)vfprintf;
> > +        print_opaque = stderr;
> > +    }
> > +
> > +    if (message_with_timestamp && !cur) {
> >           timestr = real_time_iso8601();
> > -        error_printf("%s ", timestr);
> > +        print_func(print_opaque, "%s ", timestr);
> >           g_free(timestr);
> >       }
> >       /* Only prepend guest name if -msg guest-name and -name guest=... are set */
> > -    if (error_with_guestname && error_guest_name && !monitor_cur_hmp()) {
> > -        error_printf("%s ", error_guest_name);
> > +    if (error_with_guestname && error_guest_name && !cur) {
> > +        print_func(print_opaque, "%s ", error_guest_name);
> >       }
> 
> It's worth pushing these second and third if into the first else,
> so that !cur is already true.

You've probably seen now that these 'if' blocks go away in the later
patch and the "qmessage_context_print(stderr);" that replaces them
is indeed inside the first 'else'.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 18/20] util: add support for formatting a program name in messages
  2025-09-11 18:07   ` Richard Henderson
  2025-09-11 18:08     ` Richard Henderson
@ 2025-09-12 16:33     ` Daniel P. Berrangé
  1 sibling, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-12 16:33 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

On Thu, Sep 11, 2025 at 06:07:57PM +0000, Richard Henderson wrote:
> On 9/10/25 18:03, Daniel P. Berrangé wrote:
> > @@ -157,10 +157,6 @@ static void print_loc(bool cur, error_print_func print_func, void *print_opaque)
> >       int i;
> >       const char *const *argp;
> > -    if (!cur && g_get_prgname()) {
> > -        print_func(print_opaque, "%s:", g_get_prgname());
> > -        sep = " ";
> > -    }
> 
> Last use of cur in this function is removed.

Thanks, will remove it.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 02/20] monitor: initialize global data from a constructor
  2025-09-10 18:03 ` [PATCH v3 02/20] monitor: initialize global data from a constructor Daniel P. Berrangé
@ 2025-09-17 14:07   ` Markus Armbruster
  2025-09-17 15:31     ` Daniel P. Berrangé
  0 siblings, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-17 14:07 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> Some monitor functions, most notably, monitor_cur() rely on global
> data being initialized by 'monitor_init_globals()'. The latter is
> called relatively late in startup. If code triggers error_report()
> before monitor_init_globals() is called, QEMU will abort when
> accessing the uninitialized monitor mutex.
>
> The critical monitor global data must be initialized from a
> constructor function, to improve the guarantee that it is done
> before any possible calls to monitor_cur(). Not only that, but
> the constructor must be marked to run before the default
> constructor in case any of them trigger error reporting.

Is error reporting from constructors a good idea?  I feel they're best
used for simple initializations only.

Do we actually do it?

> Note in particular that the RCU constructor will spawn a background
> thread so we might even have non-constructor QEMU code running
> concurrently with other constructors.

Ugh!

Arguably

  Fixes: e69ee454b5f9 (monitor: Make current monitor a per-coroutine property)

I never liked the @coroutine_mon hash table (which is what broke early
monitor_cur()), but accepted it for want of better ideas.

> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
  2025-09-10 23:20   ` Dr. David Alan Gilbert
  2025-09-11  8:49   ` Richard Henderson
@ 2025-09-17 14:11   ` Markus Armbruster
  2025-09-17 15:33     ` Daniel P. Berrangé
  2025-09-23 12:46   ` Philippe Mathieu-Daudé
  2025-09-23 14:28   ` Markus Armbruster
  4 siblings, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-17 14:11 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> Some code makes multiple qemu_log calls to incrementally emit
> a single message. Currently timestamps get prepended to all
> qemu_log calls, even those continuing a previous incomplete
> message.
>
> This changes the qemu_log so it skips adding a new line prefix,
> if the previous qemu_log call did NOT end with a newline.
>

Have you considered

  Fixes: 012842c07552 (log: make '-msg timestamp=on' apply to all qemu_log usage)

?

> Reported-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  util/log.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/util/log.c b/util/log.c
> index abdcb6b311..2642a55c59 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
>      }
>  }
>  
> +/*
> + * 'true' if the previous log message lacked a trailing '\n',
> + * and thus the subsequent call must skip any prefix
> + */
> +static __thread bool incomplete;

Thread-local only because we have @log_per_thread, isn't it?

> +
>  void qemu_log(const char *fmt, ...)
>  {
>      FILE *f;
> @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
>       * was emitted if we are delayed acquiring the
>       * mutex
>       */
> -    if (message_with_timestamp) {
> +    if (message_with_timestamp && !incomplete) {
>          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
>          timestr = g_date_time_format_iso8601(dt);
>      }
> @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
>          va_start(ap, fmt);
>          vfprintf(f, fmt, ap);
>          va_end(ap);
> +        incomplete = fmt[strlen(fmt) - 1] != '\n';
>          qemu_log_unlock(f);
>      }
>  }



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 02/20] monitor: initialize global data from a constructor
  2025-09-17 14:07   ` Markus Armbruster
@ 2025-09-17 15:31     ` Daniel P. Berrangé
  2025-09-18  6:30       ` Markus Armbruster
  0 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-17 15:31 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Wed, Sep 17, 2025 at 04:07:06PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > Some monitor functions, most notably, monitor_cur() rely on global
> > data being initialized by 'monitor_init_globals()'. The latter is
> > called relatively late in startup. If code triggers error_report()
> > before monitor_init_globals() is called, QEMU will abort when
> > accessing the uninitialized monitor mutex.
> >
> > The critical monitor global data must be initialized from a
> > constructor function, to improve the guarantee that it is done
> > before any possible calls to monitor_cur(). Not only that, but
> > the constructor must be marked to run before the default
> > constructor in case any of them trigger error reporting.
> 
> Is error reporting from constructors a good idea?  I feel they're best
> used for simple initializations only.

When you're down in the weeds on a given piece of code it might
not occurr that it could be used in a constructor.

The biggest usage is QOM type registration, which we've obviously
been careful (lucky) enough to keep safe.

The other common use if initializing global mutexes.

I rather wish our mutex APIs supported a static initializer
like you get with pthreads and/or glib mutexes. That would
have avoided this ordernig problem.

> 
> Do we actually do it?

Probably not, but I can't be that confident as I have not auditted
all constructors.

I accidentally created a problem myself by putting an error_report
call into the rcu constructor to debug something never realized
that would result in pain.

And then I put error_report into the RCU thread itself and thus
discovered that was running concurrently with other constructors.

> > Note in particular that the RCU constructor will spawn a background
> > thread so we might even have non-constructor QEMU code running
> > concurrently with other constructors.
> 
> Ugh!

Indeed, that was my thought when discovernig this :-(

> 
> Arguably
> 
>   Fixes: e69ee454b5f9 (monitor: Make current monitor a per-coroutine property)
> 
> I never liked the @coroutine_mon hash table (which is what broke early
> monitor_cur()), but accepted it for want of better ideas.

I spent a little time wondering if we could replace coroutine_mon with
a "__thread Monitor cur' and then update that in monitor_set_cur, but
I couldn't convince myself it would be entirely safe. So for sake of
getting the series done I took this approach and left the current
monitor stuff for another day.

> 
> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> > Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-17 14:11   ` Markus Armbruster
@ 2025-09-17 15:33     ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-17 15:33 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Wed, Sep 17, 2025 at 04:11:44PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > Some code makes multiple qemu_log calls to incrementally emit
> > a single message. Currently timestamps get prepended to all
> > qemu_log calls, even those continuing a previous incomplete
> > message.
> >
> > This changes the qemu_log so it skips adding a new line prefix,
> > if the previous qemu_log call did NOT end with a newline.
> >
> 
> Have you considered
> 
>   Fixes: 012842c07552 (log: make '-msg timestamp=on' apply to all qemu_log usage)
> 
> ?
> 
> > Reported-by: Richard Henderson <richard.henderson@linaro.org>
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  util/log.c | 9 ++++++++-
> >  1 file changed, 8 insertions(+), 1 deletion(-)
> >
> > diff --git a/util/log.c b/util/log.c
> > index abdcb6b311..2642a55c59 100644
> > --- a/util/log.c
> > +++ b/util/log.c
> > @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
> >      }
> >  }
> >  
> > +/*
> > + * 'true' if the previous log message lacked a trailing '\n',
> > + * and thus the subsequent call must skip any prefix
> > + */
> > +static __thread bool incomplete;
> 
> Thread-local only because we have @log_per_thread, isn't it?

Pretty much. If you're not using log_per_thread, then code which
incrementally emits a single line using multiple qemu_log calls
is doomed in a concurrency sitation, but this __thread at least
doesn't make the situation worse than it already is.

> 
> > +
> >  void qemu_log(const char *fmt, ...)
> >  {
> >      FILE *f;
> > @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
> >       * was emitted if we are delayed acquiring the
> >       * mutex
> >       */
> > -    if (message_with_timestamp) {
> > +    if (message_with_timestamp && !incomplete) {
> >          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
> >          timestr = g_date_time_format_iso8601(dt);
> >      }
> > @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
> >          va_start(ap, fmt);
> >          vfprintf(f, fmt, ap);
> >          va_end(ap);
> > +        incomplete = fmt[strlen(fmt) - 1] != '\n';
> >          qemu_log_unlock(f);
> >      }
> >  }
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 02/20] monitor: initialize global data from a constructor
  2025-09-17 15:31     ` Daniel P. Berrangé
@ 2025-09-18  6:30       ` Markus Armbruster
  0 siblings, 0 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-18  6:30 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Wed, Sep 17, 2025 at 04:07:06PM +0200, Markus Armbruster wrote:
>> Daniel P. Berrangé <berrange@redhat.com> writes:
>> 
>> > Some monitor functions, most notably, monitor_cur() rely on global
>> > data being initialized by 'monitor_init_globals()'. The latter is
>> > called relatively late in startup. If code triggers error_report()
>> > before monitor_init_globals() is called, QEMU will abort when
>> > accessing the uninitialized monitor mutex.
>> >
>> > The critical monitor global data must be initialized from a
>> > constructor function, to improve the guarantee that it is done
>> > before any possible calls to monitor_cur(). Not only that, but
>> > the constructor must be marked to run before the default
>> > constructor in case any of them trigger error reporting.
>> 
>> Is error reporting from constructors a good idea?  I feel they're best
>> used for simple initializations only.
>
> When you're down in the weeds on a given piece of code it might
> not occurr that it could be used in a constructor.

Fair.  The sane way to avoid that is keeping constructors super-simple.
Ideally, not call anything.  Next best, not call anything but simple
initialization functions from well-known system libraries, and our own
portability wrappers for them.

> The biggest usage is QOM type registration, which we've obviously
> been careful (lucky) enough to keep safe.
>
> The other common use if initializing global mutexes.
>
> I rather wish our mutex APIs supported a static initializer
> like you get with pthreads and/or glib mutexes. That would
> have avoided this ordernig problem.

Oh yes.  So much simpler, easier, and safer than constructors.

>> Do we actually do it?
>
> Probably not, but I can't be that confident as I have not auditted
> all constructors.

More evidence for us abusing constructors.

The constructor audit I'd like to see: dumb them down to super-simple, ...

> I accidentally created a problem myself by putting an error_report
> call into the rcu constructor to debug something never realized
> that would result in pain.

... so nobody will need to put debug prints there.

> And then I put error_report into the RCU thread itself and thus
> discovered that was running concurrently with other constructors.
>
>> > Note in particular that the RCU constructor will spawn a background
>> > thread so we might even have non-constructor QEMU code running
>> > concurrently with other constructors.
>> 
>> Ugh!
>
> Indeed, that was my thought when discovernig this :-(

The spiked pits we set up for ourselves...

>> Arguably
>> 
>>   Fixes: e69ee454b5f9 (monitor: Make current monitor a per-coroutine property)
>> 
>> I never liked the @coroutine_mon hash table (which is what broke early
>> monitor_cur()), but accepted it for want of better ideas.
>
> I spent a little time wondering if we could replace coroutine_mon with
> a "__thread Monitor cur' and then update that in monitor_set_cur, but
> I couldn't convince myself it would be entirely safe. So for sake of
> getting the series done I took this approach and left the current
> monitor stuff for another day.
>
>> 
>> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> > Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

I suggest to record our low opinion on constructor abuse in the commit
message.  As is, it almost sounds as if we considered it normal.
Starting threads there definitely isn't!

Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 03/20] system: unconditionally enable thread naming
  2025-09-10 18:03 ` [PATCH v3 03/20] system: unconditionally enable thread naming Daniel P. Berrangé
  2025-09-11 12:18   ` Ján Tomko
@ 2025-09-19  8:20   ` Markus Armbruster
  2025-09-19 13:32     ` Daniel P. Berrangé
  1 sibling, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19  8:20 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> When thread naming was introduced years ago, it was disabled by
> default and put behind a command line flag:
>
>   commit 8f480de0c91a18d550721f8d9af969ebfbda0793
>   Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
>   Date:   Thu Jan 30 10:20:31 2014 +0000
>
>     Add 'debug-threads' suboption to --name
>
> This was done based on a concern that something might depend
> on the historical thread naming. Thread names, however, were
> never promised to be part of QEMU's public API. The defaults
> will vary across platforms, so no assumptions should ever be
> made about naming.
>
> An opt-in behaviour is also unfortunately incompatible with
> RCU which creates its thread from an constructor function
> which is run before command line args are parsed. Thus the
> RCU thread lacks any name.
>
> libvirt has unconditionally enabled debug-threads=yes on all
> VMs it creates for 10 years. Interestingly this DID expose a
> bug in libvirt, as it parsed /proc/$PID/stat and could not
> cope with a space in the thread name. This was a latent
> pre-existing bug in libvirt though, and not a part of QEMU's
> API.
>
> Having thread names always available, will allow thread names
> to be included in error reports and log messags QEMU prints
> by default, which will improve ability to triage QEMU bugs.
>
> Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  docs/about/deprecated.rst |  7 +++++++
>  include/qemu/thread.h     |  1 -
>  system/vl.c               | 11 ++++++-----
>  util/qemu-thread-posix.c  | 18 +-----------------
>  util/qemu-thread-win32.c  | 27 ++++++---------------------
>  5 files changed, 20 insertions(+), 44 deletions(-)
>
> diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> index b2420732e1..7187ea15fa 100644
> --- a/docs/about/deprecated.rst
> +++ b/docs/about/deprecated.rst
> @@ -81,6 +81,13 @@ kernel since 2001. None of the board types QEMU supports need
>  ``param_struct`` support, so this option has been deprecated and will
>  be removed in a future QEMU version.
>  
> +``debug-threads`` option for ``-name``
> +''''''''''''''''''''''''''''''''''''''
> +
> +Thread ``debug-threads`` option for the ``-name`` argument is now

Do you mean "The ``debug-threads`` option"?

"option for" or "option of"?  Not a native speaker...

> +ignored. Thread naming is unconditionally enabled for all platforms
> +where it is supported.
> +
>  QEMU Machine Protocol (QMP) commands
>  ------------------------------------
>  
> diff --git a/include/qemu/thread.h b/include/qemu/thread.h
> index f0302ed01f..3a286bb3ef 100644
> --- a/include/qemu/thread.h
> +++ b/include/qemu/thread.h
> @@ -215,7 +215,6 @@ void *qemu_thread_join(QemuThread *thread);
>  void qemu_thread_get_self(QemuThread *thread);
>  bool qemu_thread_is_self(QemuThread *thread);
>  G_NORETURN void qemu_thread_exit(void *retval);
> -void qemu_thread_naming(bool enable);
>  
>  struct Notifier;
>  /**
> diff --git a/system/vl.c b/system/vl.c
> index 3b7057e6c6..a64fd90d4a 100644
> --- a/system/vl.c
> +++ b/system/vl.c
> @@ -403,9 +403,7 @@ static QemuOptsList qemu_name_opts = {
>          }, {
>              .name = "debug-threads",
>              .type = QEMU_OPT_BOOL,
> -            .help = "When enabled, name the individual threads; defaults off.\n"
> -                    "NOTE: The thread names are for debugging and not a\n"
> -                    "stable API.",
> +            .help = "DEPRECATED: thread names are always set where supported",

Please don't shout :)

We rarely note deprecation notes in command line help texts.  I found
two.

block/qcow.c:

        {
            .name = BLOCK_OPT_ENCRYPT,
            .type = QEMU_OPT_BOOL,
            .help = "Encrypt the image with format 'aes'. (Deprecated "
                    "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",
        },

block/qcow2.c:

        {                                                               \
            .name = BLOCK_OPT_ENCRYPT,                                  \
            .type = QEMU_OPT_BOOL,                                      \
            .help = "Encrypt the image with format 'aes'. (Deprecated " \
                    "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",    \
        },                                                              \
        {                                                               \

Suggest something like

            .help = "Enable thread names"
                    " (deprecated, always enabled where supported)",

>          },
>          { /* End of list */ }
>      },
> @@ -554,9 +552,12 @@ static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
>  {
>      const char *proc_name;
>  
> -    if (qemu_opt_get(opts, "debug-threads")) {
> -        qemu_thread_naming(qemu_opt_get_bool(opts, "debug-threads", false));
> +    if (qemu_opt_get(opts, "debug-threads") &&
> +        !qemu_opt_get_bool(opts, "debug-threads", false)) {
> +        fprintf(stderr, "Ignoring deprecated 'debug-threads=no' option, " \
> +                "thread naming is unconditionally enabled\n");

Not sure this is worth the trouble, but since you wrote and tested it
already...

>      }
> +
>      qemu_name = qemu_opt_get(opts, "guest");
>  
>      proc_name = qemu_opt_get(opts, "process");
> diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
> index ba725444ba..7c985b5d38 100644
> --- a/util/qemu-thread-posix.c
> +++ b/util/qemu-thread-posix.c
> @@ -22,22 +22,6 @@
>  #include <pthread_np.h>
>  #endif
>  
> -static bool name_threads;
> -
> -void qemu_thread_naming(bool enable)
> -{
> -    name_threads = enable;
> -
> -#if !defined CONFIG_PTHREAD_SETNAME_NP_W_TID && \
> -    !defined CONFIG_PTHREAD_SETNAME_NP_WO_TID && \
> -    !defined CONFIG_PTHREAD_SET_NAME_NP
> -    /* This is a debugging option, not fatal */
> -    if (enable) {
> -        fprintf(stderr, "qemu: thread naming not supported on this host\n");
> -    }
> -#endif
> -}
> -
>  static void error_exit(int err, const char *msg)
>  {
>      fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
> @@ -361,7 +345,7 @@ static void *qemu_thread_start(void *args)
>      /* Attempt to set the threads name; note that this is for debug, so
>       * we're not going to fail if we can't set it.
>       */
> -    if (name_threads && qemu_thread_args->name) {
> +    if (qemu_thread_args->name) {
>  # if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
>          pthread_setname_np(pthread_self(), qemu_thread_args->name);
>  # elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
> diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
> index ca2e0b512e..9595a5b090 100644
> --- a/util/qemu-thread-win32.c
> +++ b/util/qemu-thread-win32.c
> @@ -17,8 +17,6 @@
>  #include "qemu-thread-common.h"
>  #include <process.h>
>  
> -static bool name_threads;
> -
>  typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
>                                                   PCWSTR lpThreadDescription);
>  static pSetThreadDescription SetThreadDescriptionFunc;
> @@ -44,16 +42,6 @@ static bool load_set_thread_description(void)
>      return !!SetThreadDescriptionFunc;
>  }
>  
> -void qemu_thread_naming(bool enable)
> -{
> -    name_threads = enable;
> -
> -    if (enable && !load_set_thread_description()) {
> -        fprintf(stderr, "qemu: thread naming not supported on this host\n");
> -        name_threads = false;
> -    }
> -}
> -
>  static void error_exit(int err, const char *msg)
>  {
>      char *pstr;
> @@ -328,23 +316,20 @@ void *qemu_thread_join(QemuThread *thread)
>      return ret;
>  }
>  
> -static bool set_thread_description(HANDLE h, const char *name)
> +static void set_thread_description(HANDLE h, const char *name)
>  {
> -    HRESULT hr;
>      g_autofree wchar_t *namew = NULL;
>  
>      if (!load_set_thread_description()) {
> -        return false;
> +        return;
>      }
>  
>      namew = g_utf8_to_utf16(name, -1, NULL, NULL, NULL);
>      if (!namew) {
> -        return false;
> +        return;
>      }
>  
> -    hr = SetThreadDescriptionFunc(h, namew);
> -
> -    return SUCCEEDED(hr);
> +    SetThreadDescriptionFunc(h, namew);
>  }
>  
>  void qemu_thread_create(QemuThread *thread, const char *name,
> @@ -370,8 +355,8 @@ void qemu_thread_create(QemuThread *thread, const char *name,
>      if (!hThread) {
>          error_exit(GetLastError(), __func__);
>      }
> -    if (name_threads && name && !set_thread_description(hThread, name)) {
> -        fprintf(stderr, "qemu: failed to set thread description: %s\n", name);
> +    if (name) {
> +        set_thread_description(hThread, name);
>      }
>      CloseHandle(hThread);

Modulo nits:
Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 04/20] util: expose qemu_thread_set_name
  2025-09-10 18:03 ` [PATCH v3 04/20] util: expose qemu_thread_set_name Daniel P. Berrangé
@ 2025-09-19  8:39   ` Markus Armbruster
  2025-09-24  8:37     ` Daniel P. Berrangé
  0 siblings, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19  8:39 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> The ability to set the thread name needs to be used in a number
> of places, so expose the current impls as public methods.
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  include/qemu/thread.h    |  1 +
>  util/qemu-thread-posix.c | 30 ++++++++++++++++++------------
>  util/qemu-thread-win32.c |  6 +++---
>  3 files changed, 22 insertions(+), 15 deletions(-)
>
> diff --git a/include/qemu/thread.h b/include/qemu/thread.h
> index 3a286bb3ef..27b888ab0a 100644
> --- a/include/qemu/thread.h
> +++ b/include/qemu/thread.h
> @@ -215,6 +215,7 @@ void *qemu_thread_join(QemuThread *thread);
>  void qemu_thread_get_self(QemuThread *thread);
>  bool qemu_thread_is_self(QemuThread *thread);
>  G_NORETURN void qemu_thread_exit(void *retval);
> +void qemu_thread_set_name(const char *name);
>  
>  struct Notifier;
>  /**
> diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
> index 7c985b5d38..ddaa1de4dd 100644
> --- a/util/qemu-thread-posix.c
> +++ b/util/qemu-thread-posix.c
> @@ -329,6 +329,21 @@ static void qemu_thread_atexit_notify(void *arg)
>      notifier_list_notify(&thread_exit, NULL);
>  }
>  
> +void qemu_thread_set_name(const char *name)
> +{
> +    /*
> +     * Attempt to set the threads name; note that this is for debug, so
> +     * we're not going to fail if we can't set it.
> +     */
> +# if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> +    pthread_setname_np(pthread_self(), name);
> +# elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
> +    pthread_setname_np(name);
> +# elif defined(CONFIG_PTHREAD_SET_NAME_NP)
> +    pthread_set_name_np(pthread_self(), name);
> +# endif
> +}
> +
>  typedef struct {
>      void *(*start_routine)(void *);
>      void *arg;
> @@ -342,20 +357,11 @@ static void *qemu_thread_start(void *args)
>      void *arg = qemu_thread_args->arg;
>      void *r;
>  
> -    /* Attempt to set the threads name; note that this is for debug, so
> -     * we're not going to fail if we can't set it.
> -     */
>      if (qemu_thread_args->name) {
> -# if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> -        pthread_setname_np(pthread_self(), qemu_thread_args->name);
> -# elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
> -        pthread_setname_np(qemu_thread_args->name);
> -# elif defined(CONFIG_PTHREAD_SET_NAME_NP)
> -        pthread_set_name_np(pthread_self(), qemu_thread_args->name);
> -# endif
> +        qemu_thread_set_name(qemu_thread_args->name);

Clean factoring out up to here.

> +        QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
> +        g_free(qemu_thread_args->name);
>      }
> -    QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
> -    g_free(qemu_thread_args->name);

This part avoids

       QEMU_TSAN_ANNOTATE_THREAD_NAME(NULL);
       g_free(NULL);

The latter is an obvious no-op.  The former isn't.  Separate patch or
mention in the commit message?

>      g_free(qemu_thread_args);
>  
>      /*
> diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
> index 9595a5b090..62eaa11026 100644
> --- a/util/qemu-thread-win32.c
> +++ b/util/qemu-thread-win32.c
> @@ -316,7 +316,7 @@ void *qemu_thread_join(QemuThread *thread)
>      return ret;
>  }
>  
> -static void set_thread_description(HANDLE h, const char *name)
> +void qemu_thread_set_name(const char *name)
>  {
>      g_autofree wchar_t *namew = NULL;
>  
> @@ -329,7 +329,7 @@ static void set_thread_description(HANDLE h, const char *name)
>          return;
>      }
>  
> -    SetThreadDescriptionFunc(h, namew);
> +    SetThreadDescriptionFunc(GetCurrentThread(), namew);
>  }
>  
>  void qemu_thread_create(QemuThread *thread, const char *name,
> @@ -356,7 +356,7 @@ void qemu_thread_create(QemuThread *thread, const char *name,
       hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
                                         data, 0, &thread->tid);
       if (!hThread) {
>          error_exit(GetLastError(), __func__);
>      }
>      if (name) {
> -        set_thread_description(hThread, name);
> +        qemu_thread_set_name(name);
>      }
>      CloseHandle(hThread);

This changes the first argument of SetThreadDescriptionFunc() from the
value of _beginthreadex() to GetCurrentThread().  I'm a happy Windows
ignoramus...  sure these refer to the same thread?



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name
  2025-09-12 14:58     ` Daniel P. Berrangé
@ 2025-09-19  8:46       ` Markus Armbruster
  0 siblings, 0 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19  8:46 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Christian Schoenebeck, qemu-devel, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Philippe Mathieu-Daudé, Gerd Hoffmann,
	Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Thu, Sep 11, 2025 at 03:21:04PM +0200, Christian Schoenebeck wrote:
>> On Wednesday, September 10, 2025 8:03:42 PM CEST Daniel P. Berrangé wrote:
>> > This has greater portability than directly call pthread_setname_np,
>> > which is only 1 out of 3 possible functions for pthreads that can
>> > set the name.
>> > 
>> > The new API requires a trampoline function, since it can only set
>> > the name of the current thread.
>> > 
>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

[...]

>> Well, it does what you said, so:
>> 
>> Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
>> 
>> I just wonder whether this thread naming code couldn't be much more simplified
>> now by dropping jack_set_thread_creator() entirely, which is very seldomly
>> used at all and had another user case [1]:
>> 
>> "This function can be used in very very specialized cases where it is
>> necessary that client threads created by JACK are created by something other
>> than pthread_create(). After it is used, any threads that JACK needs for the
>> client will will be created by calling the function passed to this function.
>> 
>> No normal application/client should consider calling this. The specific case
>> for which it was created involves running win32/x86 plugins under Wine on
>> Linux, where it is necessary that all threads that might call win32 functions
>> are known to Wine."
>> 
>> [1] https://jackaudio.org/api/group__ClientThreads.html#ga157ab0ade60e266ffd26ddffdb5545af
>> 
>> However there doesn't seem to be a thread creation callback in the JACK API,
>> so the jack_set_thread_creator() bypass is still the best we can get, right?
>
> From QEMU's POV the only value we get from using the thread callback
> is that we can set the thread name so the jack thrread can be easily
> identified when debugging.  I don't think there's another easy way
> to get that set, as we can't portability set thread names from outside
> the thread.

As far as I can tell, this is due to Mac OS X.  Personally, I wouldn't
bother complicating things for that.  But whoever wrote the code in
qemu-thread-posix.c did, so ...



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 07/20] util: add API to fetch the current thread name
  2025-09-10 18:03 ` [PATCH v3 07/20] util: add API to fetch the current thread name Daniel P. Berrangé
@ 2025-09-19  8:59   ` Markus Armbruster
  2025-09-19  9:05     ` Daniel P. Berrangé
  2025-09-23 12:12   ` Markus Armbruster
  1 sibling, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19  8:59 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> This will be used to include the thread name in error reports
> in a later patch. It returns a const string stored in a thread
> local to avoid memory allocation when it is called repeatedly
> in a single thread. This makes the assumption that the thread
> name is set at the very start of the thread, which is the case
> when using qemu_thread_create.

What happens when the assumption is violated?

> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  include/qemu/thread.h    |  1 +
>  meson.build              | 21 +++++++++++++++++
>  util/qemu-thread-posix.c | 28 ++++++++++++++++++++++-
>  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
>  4 files changed, 94 insertions(+), 5 deletions(-)
>
> diff --git a/include/qemu/thread.h b/include/qemu/thread.h
> index 27b888ab0a..98cc5c41ac 100644
> --- a/include/qemu/thread.h
> +++ b/include/qemu/thread.h
> @@ -216,6 +216,7 @@ void qemu_thread_get_self(QemuThread *thread);
>  bool qemu_thread_is_self(QemuThread *thread);
>  G_NORETURN void qemu_thread_exit(void *retval);
>  void qemu_thread_set_name(const char *name);
> +const char *qemu_thread_get_name(void);
>  
>  struct Notifier;
>  /**
> diff --git a/meson.build b/meson.build
> index fa6186db33..6aa673f4b2 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2920,6 +2920,27 @@ config_host_data.set('CONFIG_PTHREAD_SET_NAME_NP', cc.links(osdep_prefix + '''
>      pthread_set_name_np(thread, "QEMU");
>      return 0;
>    }''', dependencies: threads))
> +
> +config_host_data.set('CONFIG_PTHREAD_GETNAME_NP', cc.links(osdep_prefix + '''
> +  #include <pthread.h>
> +
> +  int main(void)
> +  {
> +    char buf[16];
> +    pthread_getname_np(pthread_self(), buf, sizeof(buf));
> +    return 0;
> +  }''', dependencies: threads))
> +config_host_data.set('CONFIG_PTHREAD_GET_NAME_NP', cc.links(osdep_prefix + '''
> +  #include <pthread.h>
> +  #include <pthread_np.h>
> +
> +  int main(void)
> +  {
> +    char buf[16];
> +    pthread_get_name_np(pthread_self(), buf, sizeof(buf));
> +    return 0;
> +  }''', dependencies: threads))
> +
>  config_host_data.set('CONFIG_PTHREAD_CONDATTR_SETCLOCK', cc.links(osdep_prefix + '''
>    #include <pthread.h>
>  
> diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
> index 275445ed94..fbb94ca97b 100644
> --- a/util/qemu-thread-posix.c
> +++ b/util/qemu-thread-posix.c
> @@ -18,7 +18,7 @@
>  #include "qemu/tsan.h"
>  #include "qemu/bitmap.h"
>  
> -#ifdef CONFIG_PTHREAD_SET_NAME_NP
> +#if defined(CONFIG_PTHREAD_SET_NAME_NP) || defined(CONFIG_PTHREAD_GET_NAME_NP)
>  #include <pthread_np.h>
>  #endif
>  
> @@ -532,3 +532,29 @@ void *qemu_thread_join(QemuThread *thread)
>      }
>      return ret;
>  }
> +
> +#ifndef PTHREAD_MAX_NAMELEN_NP
> +#define PTHREAD_MAX_NAMELEN_NP 16

Feels a bit tight.  32?

> +#endif
> +
> +static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP];
> +
> +const char *qemu_thread_get_name(void)
> +{
> +    int rv;
> +    if (namebuf[0] != '\0') {
> +        return namebuf;
> +    }
> +
> +# if defined(CONFIG_PTHREAD_GETNAME_NP)
> +    rv = pthread_getname_np(pthread_self(), namebuf, sizeof(namebuf));
> +# elif defined(CONFIG_PTHREAD_GET_NAME_NP)
> +    rv = pthread_get_name_np(pthread_self(), namebuf, sizeof(namebuf));
> +# else
> +    rv = -1;
> +# endif
> +    if (rv != 0) {
> +        strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
> +    }
> +    return namebuf;
> +}
> diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
> index 7a734a7a09..e3789c20d1 100644
> --- a/util/qemu-thread-win32.c
> +++ b/util/qemu-thread-win32.c
> @@ -19,7 +19,10 @@
>  
>  typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
>                                                   PCWSTR lpThreadDescription);
> +typedef HRESULT (WINAPI *pGetThreadDescription) (HANDLE hThread,
> +                                                 PWSTR *lpThreadDescription);
>  static pSetThreadDescription SetThreadDescriptionFunc;
> +static pGetThreadDescription GetThreadDescriptionFunc;
>  static HMODULE kernel32_module;
>  
>  static void __attribute__((__constructor__(QEMU_CONSTRUCTOR_EARLY)))
> @@ -28,7 +31,7 @@ qemu_thread_init(void)
>      qemu_thread_set_name("main");
>  }
>  
> -static bool load_set_thread_description(void)
> +static bool load_thread_description(void)
>  {
>      static gsize _init_once = 0;
>  
> @@ -38,14 +41,17 @@ static bool load_set_thread_description(void)
>              SetThreadDescriptionFunc =
>                  (pSetThreadDescription)GetProcAddress(kernel32_module,
>                                                        "SetThreadDescription");
> -            if (!SetThreadDescriptionFunc) {
> +            GetThreadDescriptionFunc =
> +                (pGetThreadDescription)GetProcAddress(kernel32_module,
> +                                                      "GetThreadDescription");
> +            if (!SetThreadDescriptionFunc || !GetThreadDescriptionFunc) {
>                  FreeLibrary(kernel32_module);
>              }
>          }
>          g_once_init_leave(&_init_once, 1);
>      }
>  
> -    return !!SetThreadDescriptionFunc;
> +    return !!(SetThreadDescriptionFunc && GetThreadDescriptionFunc);
>  }
>  
>  static void error_exit(int err, const char *msg)
> @@ -326,7 +332,7 @@ void qemu_thread_set_name(const char *name)
>  {
>      g_autofree wchar_t *namew = NULL;
>  
> -    if (!load_set_thread_description()) {
> +    if (!load_thread_description()) {
>          return;
>      }
>  
> @@ -412,3 +418,38 @@ bool qemu_thread_is_self(QemuThread *thread)
>  {
>      return GetCurrentThreadId() == thread->tid;
>  }
> +
> +static __thread char namebuf[64];
> +
> +const char *qemu_thread_get_name(void)
> +{
> +    HRESULT hr;
> +    wchar_t *namew = NULL;
> +    g_autofree char *name = NULL;
> +
> +    if (namebuf[0] != '\0') {
> +        return namebuf;
> +    }
> +
> +    if (!load_thread_description()) {
> +        goto error;
> +    }
> +
> +    hr = GetThreadDescriptionFunc(GetCurrentThread(), &namew);
> +    if (!SUCCEEDED(hr)) {
> +        goto error;
> +    }
> +
> +    name = g_utf16_to_utf8(namew, -1, NULL, NULL, NULL);
> +    LocalFree(namew);
> +    if (!name) {
> +        goto error;
> +    }
> +
> +    g_strlcpy(namebuf, name, G_N_ELEMENTS(namebuf));
> +    return namebuf;
> +
> + error:
> +    strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
> +    return namebuf;
> +}



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 07/20] util: add API to fetch the current thread name
  2025-09-19  8:59   ` Markus Armbruster
@ 2025-09-19  9:05     ` Daniel P. Berrangé
  2025-09-19 11:35       ` Markus Armbruster
  0 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-19  9:05 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Fri, Sep 19, 2025 at 10:59:18AM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > This will be used to include the thread name in error reports
> > in a later patch. It returns a const string stored in a thread
> > local to avoid memory allocation when it is called repeatedly
> > in a single thread. This makes the assumption that the thread
> > name is set at the very start of the thread, which is the case
> > when using qemu_thread_create.
> 
> What happens when the assumption is violated?

You will get an operating system default thread name,
which on Linux will default to the unqualified binary
name based on argv[0]

> 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  include/qemu/thread.h    |  1 +
> >  meson.build              | 21 +++++++++++++++++
> >  util/qemu-thread-posix.c | 28 ++++++++++++++++++++++-
> >  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
> >  4 files changed, 94 insertions(+), 5 deletions(-)


> > diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
> > index 275445ed94..fbb94ca97b 100644
> > --- a/util/qemu-thread-posix.c
> > +++ b/util/qemu-thread-posix.c
> > @@ -18,7 +18,7 @@
> >  #include "qemu/tsan.h"
> >  #include "qemu/bitmap.h"
> >  
> > -#ifdef CONFIG_PTHREAD_SET_NAME_NP
> > +#if defined(CONFIG_PTHREAD_SET_NAME_NP) || defined(CONFIG_PTHREAD_GET_NAME_NP)
> >  #include <pthread_np.h>
> >  #endif
> >  
> > @@ -532,3 +532,29 @@ void *qemu_thread_join(QemuThread *thread)
> >      }
> >      return ret;
> >  }
> > +
> > +#ifndef PTHREAD_MAX_NAMELEN_NP
> > +#define PTHREAD_MAX_NAMELEN_NP 16
> 
> Feels a bit tight.  32?

On Linux this constant is not defined, but the manpage says

  The thread name is a meaningful C language string, whose length is
  restricted to 16 characters, including the terminating null byte ('\0')

so I defined the constant to match the non-Linux constant
name, but with the Linux documented max length.

> 
> > +#endif
> > +
> > +static __thread char namebuf[PTHREAD_MAX_NAMELEN_NP];
> > +
> > +const char *qemu_thread_get_name(void)
> > +{
> > +    int rv;
> > +    if (namebuf[0] != '\0') {
> > +        return namebuf;
> > +    }
> > +
> > +# if defined(CONFIG_PTHREAD_GETNAME_NP)
> > +    rv = pthread_getname_np(pthread_self(), namebuf, sizeof(namebuf));
> > +# elif defined(CONFIG_PTHREAD_GET_NAME_NP)
> > +    rv = pthread_get_name_np(pthread_self(), namebuf, sizeof(namebuf));
> > +# else
> > +    rv = -1;
> > +# endif
> > +    if (rv != 0) {
> > +        strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
> > +    }
> > +    return namebuf;
> > +}

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 07/20] util: add API to fetch the current thread name
  2025-09-19  9:05     ` Daniel P. Berrangé
@ 2025-09-19 11:35       ` Markus Armbruster
  0 siblings, 0 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19 11:35 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Fri, Sep 19, 2025 at 10:59:18AM +0200, Markus Armbruster wrote:
>> Daniel P. Berrangé <berrange@redhat.com> writes:
>> 
>> > This will be used to include the thread name in error reports
>> > in a later patch. It returns a const string stored in a thread
>> > local to avoid memory allocation when it is called repeatedly
>> > in a single thread. This makes the assumption that the thread
>> > name is set at the very start of the thread, which is the case
>> > when using qemu_thread_create.
>> 
>> What happens when the assumption is violated?
>
> You will get an operating system default thread name,
> which on Linux will default to the unqualified binary
> name based on argv[0]

Suggest something like "The thread name should be set at the very start
of the thread, which is the case when using qemu_thread_create."

>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>> > ---
>> >  include/qemu/thread.h    |  1 +
>> >  meson.build              | 21 +++++++++++++++++
>> >  util/qemu-thread-posix.c | 28 ++++++++++++++++++++++-
>> >  util/qemu-thread-win32.c | 49 ++++++++++++++++++++++++++++++++++++----
>> >  4 files changed, 94 insertions(+), 5 deletions(-)
>
>
>> > diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
>> > index 275445ed94..fbb94ca97b 100644
>> > --- a/util/qemu-thread-posix.c
>> > +++ b/util/qemu-thread-posix.c
>> > @@ -18,7 +18,7 @@
>> >  #include "qemu/tsan.h"
>> >  #include "qemu/bitmap.h"
>> >  
>> > -#ifdef CONFIG_PTHREAD_SET_NAME_NP
>> > +#if defined(CONFIG_PTHREAD_SET_NAME_NP) || defined(CONFIG_PTHREAD_GET_NAME_NP)
>> >  #include <pthread_np.h>
>> >  #endif
>> >  
>> > @@ -532,3 +532,29 @@ void *qemu_thread_join(QemuThread *thread)
>> >      }
>> >      return ret;
>> >  }
>> > +
>> > +#ifndef PTHREAD_MAX_NAMELEN_NP
>> > +#define PTHREAD_MAX_NAMELEN_NP 16
>> 
>> Feels a bit tight.  32?
>
> On Linux this constant is not defined, but the manpage says
>
>   The thread name is a meaningful C language string, whose length is
>   restricted to 16 characters, including the terminating null byte ('\0')
>
> so I defined the constant to match the non-Linux constant
> name, but with the Linux documented max length.

I see.

Maybe mention in a comment or the commit message?

[...]



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp()
  2025-09-12 15:11     ` Daniel P. Berrangé
@ 2025-09-19 11:42       ` Markus Armbruster
  0 siblings, 0 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19 11:42 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Richard Henderson, qemu-devel, qemu-block, Hanna Reitz,
	Kevin Wolf, Marc-André Lureau, Christian Schoenebeck,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Thu, Sep 11, 2025 at 05:54:48PM +0000, Richard Henderson wrote:
>> On 9/10/25 18:03, Daniel P. Berrangé wrote:
>> > The error_printf_unless_qmp() will print to the monitor if the current
>> > one is HMP, if it is QMP nothing will be printed, otherwise stderr
>> > will be used.
>> > 
>> > This scenario is easily handled by checking !monitor_cur_is_qmp() and
>> > then calling the error_printf() function.
>> > 
>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>> > ---
>> >   ui/vnc.c | 14 +++++++++-----
>> >   1 file changed, 9 insertions(+), 5 deletions(-)
>> > 
>> > diff --git a/ui/vnc.c b/ui/vnc.c
>> > index 68ca4a68e7..439d586358 100644
>> > --- a/ui/vnc.c
>> > +++ b/ui/vnc.c
>> > @@ -3530,8 +3530,10 @@ int vnc_display_password(const char *id, const char *password)
>> >           return -EINVAL;
>> >       }
>> >       if (vd->auth == VNC_AUTH_NONE) {
>> > -        error_printf_unless_qmp("If you want use passwords please enable "
>> > -                                "password auth using '-vnc ${dpy},password'.\n");
>> > +        if (!monitor_cur_is_qmp()) {
>> > +            error_printf("If you want use passwords please enable "

Maybe use the opportunity to put a comma after passwords?

>> > +                         "password auth using '-vnc ${dpy},password'.\n");
>> > +        }
>> >           return -EINVAL;
>> >       }
>> > @@ -3570,9 +3572,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
>> >           qapi_free_SocketAddress(addr);
>> >           return;
>> >       }
>> > -    error_printf_unless_qmp("VNC server running on %s:%s\n",
>> > -                            addr->u.inet.host,
>> > -                            addr->u.inet.port);
>> > +    if (!monitor_cur_is_qmp()) {
>> > +        error_printf("VNC server running on %s:%s\n",
>> > +                     addr->u.inet.host,
>> > +                     addr->u.inet.port);
>> > +    }
>> >       qapi_free_SocketAddress(addr);
>> >   }
>> 
>> With monitor_cur_hmp, you can use monitor_printf directly.
>
> We still need to be able to print to stderr when there is neither HMP
> nor QMP, which error_printf gets us, but monitor_printf would not.

monitor_printf() is fine when it's obvious that we're in HMP context.
It isn't here.

Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp
  2025-09-10 18:03 ` [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp Daniel P. Berrangé
  2025-09-11  8:50   ` Richard Henderson
@ 2025-09-19 11:42   ` Markus Armbruster
  2025-09-23 12:48   ` Philippe Mathieu-Daudé
  2 siblings, 0 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19 11:42 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> These functions only had one caller which was easily converted to
> the normal error_printf() function. Remove them as they don't add
> sufficient value.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c
  2025-09-10 18:03 ` [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c Daniel P. Berrangé
  2025-09-11  8:55   ` Richard Henderson
@ 2025-09-19 12:27   ` Markus Armbruster
  2025-09-19 13:43     ` Daniel P. Berrangé
  1 sibling, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19 12:27 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> This conceptually reverts 397d30e9401d2da96dbdf0ce49805d6d4bb68833.
> The discussion around stubs in that commit does not appear to be
> important to the current state of the codebase.

Can we figure out why Paolo's change is no longer needed?

Discussion back then:
https://lore.kernel.org/qemu-devel/37942764-b3c8-1ac1-5121-894ada7300f2@redhat.com/
https://lore.kernel.org/qemu-devel/1477326663-67817-1-git-send-email-pbonzini@redhat.com/

> This makes the error_vprintf() impl source file match that
> of error_printf(), and also match the header where it is declared.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-10 18:03 ` [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function Daniel P. Berrangé
  2025-09-11 17:52   ` Richard Henderson
@ 2025-09-19 12:43   ` Markus Armbruster
  2025-09-19 13:29     ` Daniel P. Berrangé
  1 sibling, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-19 12:43 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().

"A number of"?  I can see just one:

    int error_vprintf(const char *fmt, va_list ap)
    {
        Monitor *cur_mon = monitor_cur();

        if (cur_mon && !monitor_cur_is_qmp()) {
            return monitor_vprintf(cur_mon, fmt, ap);
        }
        return vfprintf(stderr, fmt, ap);
    }

> This is undesirable because monitor_cur_is_qmp() will itself call
> monitor_cur() again, and monitor_cur() must acquire locks and do
> hash table lookups. Introducing a monitor_cur_hmp() helper will
> combine the two operations into one reducing cost.

This made me expect the patch replaces the undesirable uses.  It does
not; the new function remains unused for now.

> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  include/monitor/monitor.h      |  1 +
>  monitor/monitor.c              | 14 ++++++++++++++
>  stubs/monitor-core.c           |  5 +++++
>  tests/unit/test-util-sockets.c |  1 +
>  4 files changed, 21 insertions(+)
>
> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> index 296690e1f1..c3b79b960a 100644
> --- a/include/monitor/monitor.h
> +++ b/include/monitor/monitor.h
> @@ -14,6 +14,7 @@ typedef struct MonitorOptions MonitorOptions;
>  extern QemuOptsList qemu_mon_opts;
>  
>  Monitor *monitor_cur(void);
> +Monitor *monitor_cur_hmp(void);
>  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon);
>  bool monitor_cur_is_qmp(void);
>  
> diff --git a/monitor/monitor.c b/monitor/monitor.c
> index e1e5dbfcbe..cff502c53e 100644
> --- a/monitor/monitor.c
> +++ b/monitor/monitor.c
> @@ -84,6 +84,20 @@ Monitor *monitor_cur(void)
>      return mon;
>  }
>  
> +Monitor *monitor_cur_hmp(void)
> +{
> +    Monitor *mon;
> +
> +    qemu_mutex_lock(&monitor_lock);
> +    mon = g_hash_table_lookup(coroutine_mon, qemu_coroutine_self());
> +    if (mon && monitor_is_qmp(mon)) {
> +        mon = NULL;
> +    }
> +    qemu_mutex_unlock(&monitor_lock);
> +
> +    return mon;
> +}
> +
>  /**
>   * Sets a new current monitor and returns the old one.
>   *
> diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
> index b498a0f1af..1e0b11ec29 100644
> --- a/stubs/monitor-core.c
> +++ b/stubs/monitor-core.c
> @@ -7,6 +7,11 @@ Monitor *monitor_cur(void)
>      return NULL;
>  }
>  
> +Monitor *monitor_cur_hmp(void)
> +{
> +    return NULL;
> +}
> +
>  bool monitor_cur_is_qmp(void)
>  {
>      return false;
> diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
> index bd48731ea2..d40813c682 100644
> --- a/tests/unit/test-util-sockets.c
> +++ b/tests/unit/test-util-sockets.c
> @@ -72,6 +72,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
>   * otherwise we get duplicate syms at link time.
>   */
>  Monitor *monitor_cur(void) { return cur_mon; }
> +Monitor *monitor_cur_hmp(void) { return cur_mon; }

@cur_mon is a fake here.  Why do you make this fake monitor HMP?  If we
somehow call error_vprintf(), it'll call monitor_vprintf(), which will
dereference the fake monitor.  Best possible outcome would be an
immediate crash.

>  bool monitor_cur_is_qmp(void) { return false; }
>  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
>  int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-19 12:43   ` Markus Armbruster
@ 2025-09-19 13:29     ` Daniel P. Berrangé
  2025-09-20  7:06       ` Markus Armbruster
  0 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-19 13:29 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Fri, Sep 19, 2025 at 02:43:41PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().
> 
> "A number of"?  I can see just one:
> 
>     int error_vprintf(const char *fmt, va_list ap)
>     {
>         Monitor *cur_mon = monitor_cur();
> 
>         if (cur_mon && !monitor_cur_is_qmp()) {
>             return monitor_vprintf(cur_mon, fmt, ap);
>         }
>         return vfprintf(stderr, fmt, ap);
>     }

Opps, that'll be referring to the other use of monitor_cur() in my
patches that I then removed when I re-ordered the series.

> 
> > This is undesirable because monitor_cur_is_qmp() will itself call
> > monitor_cur() again, and monitor_cur() must acquire locks and do
> > hash table lookups. Introducing a monitor_cur_hmp() helper will
> > combine the two operations into one reducing cost.
> 
> This made me expect the patch replaces the undesirable uses.  It does
> not; the new function remains unused for now.
> 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  include/monitor/monitor.h      |  1 +
> >  monitor/monitor.c              | 14 ++++++++++++++
> >  stubs/monitor-core.c           |  5 +++++
> >  tests/unit/test-util-sockets.c |  1 +
> >  4 files changed, 21 insertions(+)
> >
> > diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> > index 296690e1f1..c3b79b960a 100644
> > --- a/include/monitor/monitor.h
> > +++ b/include/monitor/monitor.h
> > @@ -14,6 +14,7 @@ typedef struct MonitorOptions MonitorOptions;
> >  extern QemuOptsList qemu_mon_opts;
> >  
> >  Monitor *monitor_cur(void);
> > +Monitor *monitor_cur_hmp(void);
> >  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon);
> >  bool monitor_cur_is_qmp(void);
> >  
> > diff --git a/monitor/monitor.c b/monitor/monitor.c
> > index e1e5dbfcbe..cff502c53e 100644
> > --- a/monitor/monitor.c
> > +++ b/monitor/monitor.c
> > @@ -84,6 +84,20 @@ Monitor *monitor_cur(void)
> >      return mon;
> >  }
> >  
> > +Monitor *monitor_cur_hmp(void)
> > +{
> > +    Monitor *mon;
> > +
> > +    qemu_mutex_lock(&monitor_lock);
> > +    mon = g_hash_table_lookup(coroutine_mon, qemu_coroutine_self());
> > +    if (mon && monitor_is_qmp(mon)) {
> > +        mon = NULL;
> > +    }
> > +    qemu_mutex_unlock(&monitor_lock);
> > +
> > +    return mon;
> > +}
> > +
> >  /**
> >   * Sets a new current monitor and returns the old one.
> >   *
> > diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
> > index b498a0f1af..1e0b11ec29 100644
> > --- a/stubs/monitor-core.c
> > +++ b/stubs/monitor-core.c
> > @@ -7,6 +7,11 @@ Monitor *monitor_cur(void)
> >      return NULL;
> >  }
> >  
> > +Monitor *monitor_cur_hmp(void)
> > +{
> > +    return NULL;
> > +}
> > +
> >  bool monitor_cur_is_qmp(void)
> >  {
> >      return false;
> > diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
> > index bd48731ea2..d40813c682 100644
> > --- a/tests/unit/test-util-sockets.c
> > +++ b/tests/unit/test-util-sockets.c
> > @@ -72,6 +72,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
> >   * otherwise we get duplicate syms at link time.
> >   */
> >  Monitor *monitor_cur(void) { return cur_mon; }
> > +Monitor *monitor_cur_hmp(void) { return cur_mon; }
> 
> @cur_mon is a fake here.  Why do you make this fake monitor HMP?  If we
> somehow call error_vprintf(), it'll call monitor_vprintf(), which will
> dereference the fake monitor.  Best possible outcome would be an
> immediate crash.

Current code has 'monitor_cur' return 'cur_mon', and 'monitor_cur_is_qmp'
(below)  return 'false'. IOW, the current behaviour of the stubs is that
'cur_mon' is HMP, so I just maintained those semantics.

We've stubbed monitor_vprintf() too so it'll abort() no matter what, as
we don't expect that code path to be triggered from this test suite.

> >  bool monitor_cur_is_qmp(void) { return false; }
> >  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
> >  int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 03/20] system: unconditionally enable thread naming
  2025-09-19  8:20   ` Markus Armbruster
@ 2025-09-19 13:32     ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-19 13:32 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Fri, Sep 19, 2025 at 10:20:51AM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > When thread naming was introduced years ago, it was disabled by
> > default and put behind a command line flag:
> >
> >   commit 8f480de0c91a18d550721f8d9af969ebfbda0793
> >   Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
> >   Date:   Thu Jan 30 10:20:31 2014 +0000
> >
> >     Add 'debug-threads' suboption to --name
> >
> > This was done based on a concern that something might depend
> > on the historical thread naming. Thread names, however, were
> > never promised to be part of QEMU's public API. The defaults
> > will vary across platforms, so no assumptions should ever be
> > made about naming.
> >
> > An opt-in behaviour is also unfortunately incompatible with
> > RCU which creates its thread from an constructor function
> > which is run before command line args are parsed. Thus the
> > RCU thread lacks any name.
> >
> > libvirt has unconditionally enabled debug-threads=yes on all
> > VMs it creates for 10 years. Interestingly this DID expose a
> > bug in libvirt, as it parsed /proc/$PID/stat and could not
> > cope with a space in the thread name. This was a latent
> > pre-existing bug in libvirt though, and not a part of QEMU's
> > API.
> >
> > Having thread names always available, will allow thread names
> > to be included in error reports and log messags QEMU prints
> > by default, which will improve ability to triage QEMU bugs.
> >
> > Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  docs/about/deprecated.rst |  7 +++++++
> >  include/qemu/thread.h     |  1 -
> >  system/vl.c               | 11 ++++++-----
> >  util/qemu-thread-posix.c  | 18 +-----------------
> >  util/qemu-thread-win32.c  | 27 ++++++---------------------
> >  5 files changed, 20 insertions(+), 44 deletions(-)
> >
> > diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> > index b2420732e1..7187ea15fa 100644
> > --- a/docs/about/deprecated.rst
> > +++ b/docs/about/deprecated.rst
> > @@ -81,6 +81,13 @@ kernel since 2001. None of the board types QEMU supports need
> >  ``param_struct`` support, so this option has been deprecated and will
> >  be removed in a future QEMU version.
> >  
> > +``debug-threads`` option for ``-name``
> > +''''''''''''''''''''''''''''''''''''''
> > +
> > +Thread ``debug-threads`` option for the ``-name`` argument is now
> 
> Do you mean "The ``debug-threads`` option"?

Opps, yes indeed.

> 
> "option for" or "option of"?  Not a native speaker...

"of" is probably better.

> 
> > +ignored. Thread naming is unconditionally enabled for all platforms
> > +where it is supported.
> > +
> >  QEMU Machine Protocol (QMP) commands
> >  ------------------------------------
> >  
> > diff --git a/include/qemu/thread.h b/include/qemu/thread.h
> > index f0302ed01f..3a286bb3ef 100644
> > --- a/include/qemu/thread.h
> > +++ b/include/qemu/thread.h
> > @@ -215,7 +215,6 @@ void *qemu_thread_join(QemuThread *thread);
> >  void qemu_thread_get_self(QemuThread *thread);
> >  bool qemu_thread_is_self(QemuThread *thread);
> >  G_NORETURN void qemu_thread_exit(void *retval);
> > -void qemu_thread_naming(bool enable);
> >  
> >  struct Notifier;
> >  /**
> > diff --git a/system/vl.c b/system/vl.c
> > index 3b7057e6c6..a64fd90d4a 100644
> > --- a/system/vl.c
> > +++ b/system/vl.c
> > @@ -403,9 +403,7 @@ static QemuOptsList qemu_name_opts = {
> >          }, {
> >              .name = "debug-threads",
> >              .type = QEMU_OPT_BOOL,
> > -            .help = "When enabled, name the individual threads; defaults off.\n"
> > -                    "NOTE: The thread names are for debugging and not a\n"
> > -                    "stable API.",
> > +            .help = "DEPRECATED: thread names are always set where supported",
> 
> Please don't shout :)

Hmmm, yes.

> We rarely note deprecation notes in command line help texts.  I found
> two.
> 
> block/qcow.c:
> 
>         {
>             .name = BLOCK_OPT_ENCRYPT,
>             .type = QEMU_OPT_BOOL,
>             .help = "Encrypt the image with format 'aes'. (Deprecated "
>                     "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",
>         },
> 
> block/qcow2.c:
> 
>         {                                                               \
>             .name = BLOCK_OPT_ENCRYPT,                                  \
>             .type = QEMU_OPT_BOOL,                                      \
>             .help = "Encrypt the image with format 'aes'. (Deprecated " \
>                     "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",    \
>         },                                                              \
>         {                                                               \
> 
> Suggest something like
> 
>             .help = "Enable thread names"
>                     " (deprecated, always enabled where supported)",

Sure.

> 
> >          },
> >          { /* End of list */ }
> >      },
> > @@ -554,9 +552,12 @@ static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
> >  {
> >      const char *proc_name;
> >  
> > -    if (qemu_opt_get(opts, "debug-threads")) {
> > -        qemu_thread_naming(qemu_opt_get_bool(opts, "debug-threads", false));
> > +    if (qemu_opt_get(opts, "debug-threads") &&
> > +        !qemu_opt_get_bool(opts, "debug-threads", false)) {
> > +        fprintf(stderr, "Ignoring deprecated 'debug-threads=no' option, " \
> > +                "thread naming is unconditionally enabled\n");
> 
> Not sure this is worth the trouble, but since you wrote and tested it
> already...

As a general rule I like there to be a printf() in any code path that
touches a deprecation, because we know  people often won't actually
read the docs. The message is helping them know what's coming soon


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c
  2025-09-19 12:27   ` Markus Armbruster
@ 2025-09-19 13:43     ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-19 13:43 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Fri, Sep 19, 2025 at 02:27:20PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > This conceptually reverts 397d30e9401d2da96dbdf0ce49805d6d4bb68833.
> > The discussion around stubs in that commit does not appear to be
> > important to the current state of the codebase.
> 
> Can we figure out why Paolo's change is no longer needed?
> 
> Discussion back then:
> https://lore.kernel.org/qemu-devel/37942764-b3c8-1ac1-5121-894ada7300f2@redhat.com/
> https://lore.kernel.org/qemu-devel/1477326663-67817-1-git-send-email-pbonzini@redhat.com/

I'm wrong, this change of mine is broken because it messes up the output
of test-vmstate still

> 
> > This makes the error_vprintf() impl source file match that
> > of error_printf(), and also match the header where it is declared.
> >
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-19 13:29     ` Daniel P. Berrangé
@ 2025-09-20  7:06       ` Markus Armbruster
  2025-09-20 11:54         ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-20  7:06 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Fri, Sep 19, 2025 at 02:43:41PM +0200, Markus Armbruster wrote:
>> Daniel P. Berrangé <berrange@redhat.com> writes:
>> 
>> > A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().
>> 
>> "A number of"?  I can see just one:
>> 
>>     int error_vprintf(const char *fmt, va_list ap)
>>     {
>>         Monitor *cur_mon = monitor_cur();
>> 
>>         if (cur_mon && !monitor_cur_is_qmp()) {
>>             return monitor_vprintf(cur_mon, fmt, ap);
>>         }
>>         return vfprintf(stderr, fmt, ap);
>>     }
>
> Opps, that'll be referring to the other use of monitor_cur() in my
> patches that I then removed when I re-ordered the series.
>
>> 
>> > This is undesirable because monitor_cur_is_qmp() will itself call
>> > monitor_cur() again, and monitor_cur() must acquire locks and do
>> > hash table lookups. Introducing a monitor_cur_hmp() helper will
>> > combine the two operations into one reducing cost.

I think the actual interface flaw is having monitor_cur_is_qmp().

In master, monitor_cur_is_qmp() is only used in monitor/monitor.c.  Both
call sites have the value of monitor_cur() available as @cur_mon.
They'd be better off calling monitor_is_qmp(cur_mon).

Note that in master nothing outside monitor/ cares whether a monitor is
QMP or HMP.  I like that.

Your series doesn't preserve this property.

You move the first call site error_vprintf() from monitor/monitor.c to
util/error-report.c in PATCH 11.  QMP vs. HMP is no longer encapsulated.
Slighly irksome.

PATCH 13 replaces monitor_cur_is_qmp() by monitor_cur_hmp() there, and
PATCH 14 adds a second use.

The second call site error_vprintf() gets inlined into ui/vnc.c by PATCH
10.  QMP vs. HMP leaks into ui/.  Again, only slighly irksome.

We could instead preserve the status quo: error_vprintf() stays put in
monitor.c, error_printf_unless_qmp() stays around.

Independently, I feel we should drop monitor_cur_is_qmp() and not
introduce monitor_cur_hmp().  Just use monitor_cur() and
monitor_is_qmp().  Move monitor_is_qmp() from monitor-internal.h to
monitor.h if it's needed outside the monitor.  Have to make it not
inline then.

>> This made me expect the patch replaces the undesirable uses.  It does
>> not; the new function remains unused for now.
>> 
>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>> > ---
>> >  include/monitor/monitor.h      |  1 +
>> >  monitor/monitor.c              | 14 ++++++++++++++
>> >  stubs/monitor-core.c           |  5 +++++
>> >  tests/unit/test-util-sockets.c |  1 +
>> >  4 files changed, 21 insertions(+)
>> >
>> > diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
>> > index 296690e1f1..c3b79b960a 100644
>> > --- a/include/monitor/monitor.h
>> > +++ b/include/monitor/monitor.h
>> > @@ -14,6 +14,7 @@ typedef struct MonitorOptions MonitorOptions;
>> >  extern QemuOptsList qemu_mon_opts;
>> >  
>> >  Monitor *monitor_cur(void);
>> > +Monitor *monitor_cur_hmp(void);
>> >  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon);
>> >  bool monitor_cur_is_qmp(void);
>> >  
>> > diff --git a/monitor/monitor.c b/monitor/monitor.c
>> > index e1e5dbfcbe..cff502c53e 100644
>> > --- a/monitor/monitor.c
>> > +++ b/monitor/monitor.c
>> > @@ -84,6 +84,20 @@ Monitor *monitor_cur(void)
>> >      return mon;
>> >  }
>> >  
>> > +Monitor *monitor_cur_hmp(void)
>> > +{
>> > +    Monitor *mon;
>> > +
>> > +    qemu_mutex_lock(&monitor_lock);
>> > +    mon = g_hash_table_lookup(coroutine_mon, qemu_coroutine_self());
>> > +    if (mon && monitor_is_qmp(mon)) {
>> > +        mon = NULL;
>> > +    }
>> > +    qemu_mutex_unlock(&monitor_lock);
>> > +
>> > +    return mon;
>> > +}
>> > +
>> >  /**
>> >   * Sets a new current monitor and returns the old one.
>> >   *
>> > diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
>> > index b498a0f1af..1e0b11ec29 100644
>> > --- a/stubs/monitor-core.c
>> > +++ b/stubs/monitor-core.c
>> > @@ -7,6 +7,11 @@ Monitor *monitor_cur(void)
>> >      return NULL;
>> >  }
>> >  
>> > +Monitor *monitor_cur_hmp(void)
>> > +{
>> > +    return NULL;
>> > +}
>> > +
>> >  bool monitor_cur_is_qmp(void)
>> >  {
>> >      return false;
>> > diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
>> > index bd48731ea2..d40813c682 100644
>> > --- a/tests/unit/test-util-sockets.c
>> > +++ b/tests/unit/test-util-sockets.c
>> > @@ -72,6 +72,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
>> >   * otherwise we get duplicate syms at link time.
>> >   */
>> >  Monitor *monitor_cur(void) { return cur_mon; }
>> > +Monitor *monitor_cur_hmp(void) { return cur_mon; }
>> 
>> @cur_mon is a fake here.  Why do you make this fake monitor HMP?  If we
>> somehow call error_vprintf(), it'll call monitor_vprintf(), which will
>> dereference the fake monitor.  Best possible outcome would be an
>> immediate crash.
>
> Current code has 'monitor_cur' return 'cur_mon', and 'monitor_cur_is_qmp'
> (below)  return 'false'. IOW, the current behaviour of the stubs is that
> 'cur_mon' is HMP, so I just maintained those semantics.

monitor_cur_is_qmp() below is from your PATCH 11, though.

> We've stubbed monitor_vprintf() too so it'll abort() no matter what, as
> we don't expect that code path to be triggered from this test suite.

Point!  Nevermind :)

>> >  bool monitor_cur_is_qmp(void) { return false; }
>> >  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
>> >  int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
>
>
> With regards,
> Daniel



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-20  7:06       ` Markus Armbruster
@ 2025-09-20 11:54         ` Dr. David Alan Gilbert
  2025-09-22  8:38           ` Markus Armbruster
  0 siblings, 1 reply; 84+ messages in thread
From: Dr. David Alan Gilbert @ 2025-09-20 11:54 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Daniel P. Berrangé, qemu-devel, qemu-block, Hanna Reitz,
	Kevin Wolf, Marc-André Lureau, Christian Schoenebeck,
	Richard Henderson, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini

* Markus Armbruster (armbru@redhat.com) wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > On Fri, Sep 19, 2025 at 02:43:41PM +0200, Markus Armbruster wrote:
> >> Daniel P. Berrangé <berrange@redhat.com> writes:
> >> 
> >> > A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().
> >> 
> >> "A number of"?  I can see just one:
> >> 
> >>     int error_vprintf(const char *fmt, va_list ap)
> >>     {
> >>         Monitor *cur_mon = monitor_cur();
> >> 
> >>         if (cur_mon && !monitor_cur_is_qmp()) {
> >>             return monitor_vprintf(cur_mon, fmt, ap);
> >>         }
> >>         return vfprintf(stderr, fmt, ap);
> >>     }
> >
> > Opps, that'll be referring to the other use of monitor_cur() in my
> > patches that I then removed when I re-ordered the series.
> >
> >> 
> >> > This is undesirable because monitor_cur_is_qmp() will itself call
> >> > monitor_cur() again, and monitor_cur() must acquire locks and do
> >> > hash table lookups. Introducing a monitor_cur_hmp() helper will
> >> > combine the two operations into one reducing cost.
> 
> I think the actual interface flaw is having monitor_cur_is_qmp().
> 
> In master, monitor_cur_is_qmp() is only used in monitor/monitor.c.  Both
> call sites have the value of monitor_cur() available as @cur_mon.
> They'd be better off calling monitor_is_qmp(cur_mon).
> 
> Note that in master nothing outside monitor/ cares whether a monitor is
> QMP or HMP.  I like that.
> 
> Your series doesn't preserve this property.
> 
> You move the first call site error_vprintf() from monitor/monitor.c to
> util/error-report.c in PATCH 11.  QMP vs. HMP is no longer encapsulated.
> Slighly irksome.

How about a slightly simpler approach, looking above we have:

> >>         if (cur_mon && !monitor_cur_is_qmp()) {
> >>             return monitor_vprintf(cur_mon, fmt, ap);
> >>         }
> >>         return vfprintf(stderr, fmt, ap);

I think we could replace this with:

  ret = monitor_vprintf(cur_mon, fmt, ap);
  if (ret == -1) {
       ret = vfprintf(stderr, fmt, ap);
  }
  return ret;

monitor_vprintf already -1 exits if !mon or monitor_is_qmp(mon)

Keeps the encapsulation, and is now 'print via the monitor but if it
can't do it, use printf'

Dave


> PATCH 13 replaces monitor_cur_is_qmp() by monitor_cur_hmp() there, and
> PATCH 14 adds a second use.
> 
> The second call site error_vprintf() gets inlined into ui/vnc.c by PATCH
> 10.  QMP vs. HMP leaks into ui/.  Again, only slighly irksome.
> 
> We could instead preserve the status quo: error_vprintf() stays put in
> monitor.c, error_printf_unless_qmp() stays around.
> 
> Independently, I feel we should drop monitor_cur_is_qmp() and not
> introduce monitor_cur_hmp().  Just use monitor_cur() and
> monitor_is_qmp().  Move monitor_is_qmp() from monitor-internal.h to
> monitor.h if it's needed outside the monitor.  Have to make it not
> inline then.
> 
> >> This made me expect the patch replaces the undesirable uses.  It does
> >> not; the new function remains unused for now.
> >> 
> >> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> >> > ---
> >> >  include/monitor/monitor.h      |  1 +
> >> >  monitor/monitor.c              | 14 ++++++++++++++
> >> >  stubs/monitor-core.c           |  5 +++++
> >> >  tests/unit/test-util-sockets.c |  1 +
> >> >  4 files changed, 21 insertions(+)
> >> >
> >> > diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> >> > index 296690e1f1..c3b79b960a 100644
> >> > --- a/include/monitor/monitor.h
> >> > +++ b/include/monitor/monitor.h
> >> > @@ -14,6 +14,7 @@ typedef struct MonitorOptions MonitorOptions;
> >> >  extern QemuOptsList qemu_mon_opts;
> >> >  
> >> >  Monitor *monitor_cur(void);
> >> > +Monitor *monitor_cur_hmp(void);
> >> >  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon);
> >> >  bool monitor_cur_is_qmp(void);
> >> >  
> >> > diff --git a/monitor/monitor.c b/monitor/monitor.c
> >> > index e1e5dbfcbe..cff502c53e 100644
> >> > --- a/monitor/monitor.c
> >> > +++ b/monitor/monitor.c
> >> > @@ -84,6 +84,20 @@ Monitor *monitor_cur(void)
> >> >      return mon;
> >> >  }
> >> >  
> >> > +Monitor *monitor_cur_hmp(void)
> >> > +{
> >> > +    Monitor *mon;
> >> > +
> >> > +    qemu_mutex_lock(&monitor_lock);
> >> > +    mon = g_hash_table_lookup(coroutine_mon, qemu_coroutine_self());
> >> > +    if (mon && monitor_is_qmp(mon)) {
> >> > +        mon = NULL;
> >> > +    }
> >> > +    qemu_mutex_unlock(&monitor_lock);
> >> > +
> >> > +    return mon;
> >> > +}
> >> > +
> >> >  /**
> >> >   * Sets a new current monitor and returns the old one.
> >> >   *
> >> > diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
> >> > index b498a0f1af..1e0b11ec29 100644
> >> > --- a/stubs/monitor-core.c
> >> > +++ b/stubs/monitor-core.c
> >> > @@ -7,6 +7,11 @@ Monitor *monitor_cur(void)
> >> >      return NULL;
> >> >  }
> >> >  
> >> > +Monitor *monitor_cur_hmp(void)
> >> > +{
> >> > +    return NULL;
> >> > +}
> >> > +
> >> >  bool monitor_cur_is_qmp(void)
> >> >  {
> >> >      return false;
> >> > diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
> >> > index bd48731ea2..d40813c682 100644
> >> > --- a/tests/unit/test-util-sockets.c
> >> > +++ b/tests/unit/test-util-sockets.c
> >> > @@ -72,6 +72,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
> >> >   * otherwise we get duplicate syms at link time.
> >> >   */
> >> >  Monitor *monitor_cur(void) { return cur_mon; }
> >> > +Monitor *monitor_cur_hmp(void) { return cur_mon; }
> >> 
> >> @cur_mon is a fake here.  Why do you make this fake monitor HMP?  If we
> >> somehow call error_vprintf(), it'll call monitor_vprintf(), which will
> >> dereference the fake monitor.  Best possible outcome would be an
> >> immediate crash.
> >
> > Current code has 'monitor_cur' return 'cur_mon', and 'monitor_cur_is_qmp'
> > (below)  return 'false'. IOW, the current behaviour of the stubs is that
> > 'cur_mon' is HMP, so I just maintained those semantics.
> 
> monitor_cur_is_qmp() below is from your PATCH 11, though.
> 
> > We've stubbed monitor_vprintf() too so it'll abort() no matter what, as
> > we don't expect that code path to be triggered from this test suite.
> 
> Point!  Nevermind :)
> 
> >> >  bool monitor_cur_is_qmp(void) { return false; }
> >> >  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
> >> >  int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
> >
> >
> > With regards,
> > Daniel
> 
-- 
 -----Open up your eyes, open up your mind, open up your code -------   
/ Dr. David Alan Gilbert    |       Running GNU/Linux       | Happy  \ 
\        dave @ treblig.org |                               | In Hex /
 \ _________________________|_____ http://www.treblig.org   |_______/


^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-20 11:54         ` Dr. David Alan Gilbert
@ 2025-09-22  8:38           ` Markus Armbruster
  2025-09-24 16:09             ` Daniel P. Berrangé
  0 siblings, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-22  8:38 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Daniel P. Berrangé, qemu-devel, qemu-block, Hanna Reitz,
	Kevin Wolf, Marc-André Lureau, Christian Schoenebeck,
	Richard Henderson, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini

"Dr. David Alan Gilbert" <dave@treblig.org> writes:

> * Markus Armbruster (armbru@redhat.com) wrote:
>> Daniel P. Berrangé <berrange@redhat.com> writes:
>> 
>> > On Fri, Sep 19, 2025 at 02:43:41PM +0200, Markus Armbruster wrote:
>> >> Daniel P. Berrangé <berrange@redhat.com> writes:
>> >> 
>> >> > A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().
>> >> 
>> >> "A number of"?  I can see just one:
>> >> 
>> >>     int error_vprintf(const char *fmt, va_list ap)
>> >>     {
>> >>         Monitor *cur_mon = monitor_cur();
>> >> 
>> >>         if (cur_mon && !monitor_cur_is_qmp()) {
>> >>             return monitor_vprintf(cur_mon, fmt, ap);
>> >>         }
>> >>         return vfprintf(stderr, fmt, ap);
>> >>     }
>> >
>> > Opps, that'll be referring to the other use of monitor_cur() in my
>> > patches that I then removed when I re-ordered the series.
>> >
>> >> 
>> >> > This is undesirable because monitor_cur_is_qmp() will itself call
>> >> > monitor_cur() again, and monitor_cur() must acquire locks and do
>> >> > hash table lookups. Introducing a monitor_cur_hmp() helper will
>> >> > combine the two operations into one reducing cost.
>> 
>> I think the actual interface flaw is having monitor_cur_is_qmp().
>> 
>> In master, monitor_cur_is_qmp() is only used in monitor/monitor.c.  Both
>> call sites have the value of monitor_cur() available as @cur_mon.
>> They'd be better off calling monitor_is_qmp(cur_mon).
>> 
>> Note that in master nothing outside monitor/ cares whether a monitor is
>> QMP or HMP.  I like that.
>> 
>> Your series doesn't preserve this property.
>> 
>> You move the first call site error_vprintf() from monitor/monitor.c to
>> util/error-report.c in PATCH 11.  QMP vs. HMP is no longer encapsulated.
>> Slighly irksome.
>
> How about a slightly simpler approach, looking above we have:
>
>> >>         if (cur_mon && !monitor_cur_is_qmp()) {
>> >>             return monitor_vprintf(cur_mon, fmt, ap);
>> >>         }
>> >>         return vfprintf(stderr, fmt, ap);
>
> I think we could replace this with:
>
>   ret = monitor_vprintf(cur_mon, fmt, ap);
>   if (ret == -1) {
>        ret = vfprintf(stderr, fmt, ap);
>   }
>   return ret;
>
> monitor_vprintf already -1 exits if !mon or monitor_is_qmp(mon)
>
> Keeps the encapsulation, and is now 'print via the monitor but if it
> can't do it, use printf'

monitor_printf() fails when passed a null monitor[*] or a QMP monitor.
Reporting the error to stderr then is probably better than swallowing
it.  Same if the function somehow picks up more failure modes.

I like it.

One could perhaps object that it makes "report to HMP or else stderr"
less obvious if you don't already know that monitor_vprintf() only
prints to HMP.  I'm okay with that.



[*] Feels more like a programming error, but we can ignore this
distraction.



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 13/20] util: don't skip error prefixes when QMP is active
  2025-09-10 18:03 ` [PATCH v3 13/20] util: don't skip error prefixes when QMP is active Daniel P. Berrangé
@ 2025-09-22  8:43   ` Markus Armbruster
  0 siblings, 0 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-22  8:43 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> The vreport() function will print to HMP if available, otherwise
> to stderr. In the event that vreport() is called during execution
> of a QMP command, it will print to stderr, but mistakenly omit the
> message prefixes (timestamp, guest name, program name).
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  util/error-report.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/util/error-report.c b/util/error-report.c
> index 79b6f23e64..c0fcf388de 100644
> --- a/util/error-report.c
> +++ b/util/error-report.c
> @@ -34,9 +34,9 @@ const char *error_guest_name;
>   */
>  int error_vprintf(const char *fmt, va_list ap)
>  {
> -    Monitor *cur_mon = monitor_cur();
> +    Monitor *cur_mon = monitor_cur_hmp();
>  
> -    if (cur_mon && !monitor_cur_is_qmp()) {
> +    if (cur_mon) {
>          return monitor_vprintf(cur_mon, fmt, ap);
>      }
>      return vfprintf(stderr, fmt, ap);

This isn't part of the fix, it merely puts monitor_cur_hmp() to use.  It
we decide we want that function (see discussion of previous patch), then
I'd squash this hunk into the patch that creates it.

> @@ -157,7 +157,7 @@ static void print_loc(void)
>      int i;
>      const char *const *argp;
>  
> -    if (!monitor_cur() && g_get_prgname()) {
> +    if (!monitor_cur_hmp() && g_get_prgname()) {
>          error_printf("%s:", g_get_prgname());
>          sep = " ";
>      }
> @@ -201,14 +201,14 @@ static void vreport(report_type type, const char *fmt, va_list ap)
>  {
>      gchar *timestr;
>  
> -    if (message_with_timestamp && !monitor_cur()) {
> +    if (message_with_timestamp && !monitor_cur_hmp()) {
>          timestr = real_time_iso8601();
>          error_printf("%s ", timestr);
>          g_free(timestr);
>      }
>  
>      /* Only prepend guest name if -msg guest-name and -name guest=... are set */
> -    if (error_with_guestname && error_guest_name && !monitor_cur()) {
> +    if (error_with_guestname && error_guest_name && !monitor_cur_hmp()) {
>          error_printf("%s ", error_guest_name);
>      }

Yup, these fix a bug.



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 14/20] util: fix interleaving of error & trace output
  2025-09-10 18:03 ` [PATCH v3 14/20] util: fix interleaving of error & trace output Daniel P. Berrangé
  2025-09-11 18:01   ` Richard Henderson
  2025-09-11 18:05   ` Richard Henderson
@ 2025-09-22 12:16   ` Markus Armbruster
  2 siblings, 0 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-22 12:16 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> The monitor_cur_hmp() function will acquire/release mutex locks, which
> will trigger trace probes, which can in turn trigger qemu_log() calls.
> vreport() calls monitor_cur() multiple times through its execution
> both directly and indirectly via error_vprintf().

This issue goes back to commit e69ee454b5f9 (monitor: Make current
monitor a per-coroutine property).  I've always disliked the hash table
(which is why we need to take the mutex), and now I dislike it even
more.  See also my review of PATCH 02.

I'd love to have a lockless monitor_cur() again.  But I don't have one
up my sleeve, so we need to work around the issue somehow.

> The result is that the prefix information printed by vreport() gets
> interleaved with qemu_log() output, when run outside the context of
> an HMP command dispatcher. This can be seen with:

[...]

> To avoid this interleaving (as well as reduce the huge number of
> mutex lock/unlock calls) we need to ensure that monitor_cur_hmp() is
> only called once at the start of vreport(), and if no HMP is present,
> no further monitor APIs can be called.
>
> This implies error_[v]printf() cannot be called from vreport().
>
> Instead a decision about whether output will go to monitor_[v]printf()
> or fprintf() must be made upfront, and then those functions called
> directly.
>
>  $ qemu-system-x86_64
>      -msg timestamp=on,guest-name=on
>      -display none
>      -object tls-creds-x509,id=f,dir=fish
>      -name fish
>      -d trace:qemu_mutex*
>    2025-09-10T16:31:22.701691Z qemu_mutex_unlock released mutex 0x5626fd3b84c0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>    2025-09-10T16:31:22.701728Z qemu_mutex_lock waiting on mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>    2025-09-10T16:31:22.701730Z qemu_mutex_locked taken mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>    2025-09-10T16:31:22.701732Z qemu_mutex_unlock released mutex 0x5626fd3b53e0 (/var/home/berrange/src/virt/qemu/include/qemu/lockable.h:56)
>    2025-09-10T16:31:22.703989Z qemu_mutex_lock waiting on mutex 0x5626fd3b5560 (../monitor/monitor.c:91)
>    2025-09-10T16:31:22.703996Z qemu_mutex_locked taken mutex 0x5626fd3b5560 (../monitor/monitor.c:91)
>    2025-09-10T16:31:22.703999Z qemu_mutex_unlock released mutex 0x5626fd3b5560 (../monitor/monitor.c:96)
>    2025-09-10T16:31:22.704000Z fish qemu-system-x86_64: Unable to access credentials fish/ca-cert.pem: No such file or directory
>
> This change requires adding a stub for monitor_printf() since that
> is now called directly by vreport(), where monitor_vprintf() was
> only needed previously.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  stubs/monitor-core.c           |  5 +++
>  tests/unit/test-util-sockets.c |  1 +
>  util/error-report.c            | 60 ++++++++++++++++++++++++----------
>  3 files changed, 48 insertions(+), 18 deletions(-)
>
> diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
> index 1e0b11ec29..70b1f7a994 100644
> --- a/stubs/monitor-core.c
> +++ b/stubs/monitor-core.c
> @@ -30,3 +30,8 @@ int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
>  {
>      abort();
>  }
> +
> +int monitor_printf(Monitor *mon, const char *fmt, ...)
> +{
> +    abort();
> +}
> diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
> index d40813c682..53733163dd 100644
> --- a/tests/unit/test-util-sockets.c
> +++ b/tests/unit/test-util-sockets.c
> @@ -76,6 +76,7 @@ Monitor *monitor_cur_hmp(void) { return cur_mon; }
>  bool monitor_cur_is_qmp(void) { return false; }
>  Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
>  int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
> +int monitor_printf(Monitor *mon, const char *fmt, ...) { abort(); }
>  
>  #ifndef _WIN32
>  static void test_socket_fd_pass_name_good(void)
> diff --git a/util/error-report.c b/util/error-report.c
> index c0fcf388de..6c887047e3 100644
> --- a/util/error-report.c
> +++ b/util/error-report.c
> @@ -29,6 +29,9 @@ bool message_with_timestamp;
>  bool error_with_guestname;
>  const char *error_guest_name;
>  
> +typedef void (*error_print_func)(void *opaque, const char *fmt, ...);
> +typedef void (*error_print_vfunc)(void *opaque, const char *fmt, va_list ap);
> +
>  /*
>   * Print to current monitor if we have one, else to stderr.
>   */
> @@ -151,34 +154,34 @@ void loc_set_file(const char *fname, int lno)
>  /*
>   * Print current location to current monitor if we have one, else to stderr.
>   */
> -static void print_loc(void)
> +static void print_loc(bool cur, error_print_func print_func, void *print_opaque)
>  {
>      const char *sep = "";
>      int i;
>      const char *const *argp;
>  
> -    if (!monitor_cur_hmp() && g_get_prgname()) {
> -        error_printf("%s:", g_get_prgname());
> +    if (!cur && g_get_prgname()) {
> +        print_func(print_opaque, "%s:", g_get_prgname());
>          sep = " ";
>      }
>      switch (cur_loc->kind) {
>      case LOC_CMDLINE:
>          argp = cur_loc->ptr;
>          for (i = 0; i < cur_loc->num; i++) {
> -            error_printf("%s%s", sep, argp[i]);
> +            print_func(print_opaque, "%s%s", sep, argp[i]);
>              sep = " ";
>          }
> -        error_printf(": ");
> +        print_func(print_opaque, ": ");
>          break;
>      case LOC_FILE:
> -        error_printf("%s:", (const char *)cur_loc->ptr);
> +        print_func(print_opaque, "%s:", (const char *)cur_loc->ptr);
>          if (cur_loc->num) {
> -            error_printf("%d:", cur_loc->num);
> +            print_func(print_opaque, "%d:", cur_loc->num);
>          }
> -        error_printf(" ");
> +        print_func(print_opaque, " ");
>          break;
>      default:
> -        error_printf("%s", sep);
> +        print_func(print_opaque, "%s", sep);
>      }
>  }
>  
> @@ -199,34 +202,55 @@ real_time_iso8601(void)
>  G_GNUC_PRINTF(2, 0)
>  static void vreport(report_type type, const char *fmt, va_list ap)
>  {
> +    /*
> +     * Calling monitor_cur_hmp() will acquire/release mutexes,
> +     * which triggers trace probes, which can trigger
> +     * qemu_log calls, which would interleave with output
> +     * from this. Hence cache the monitor handle upfront
> +     * so any tracing appears before we start outputting.
> +     */
> +    Monitor *cur = monitor_cur_hmp();
> +    error_print_func print_func;
> +    error_print_vfunc print_vfunc;
> +    void *print_opaque;
>      gchar *timestr;
>  
> -    if (message_with_timestamp && !monitor_cur_hmp()) {
> +    if (cur) {
> +        print_func = (error_print_func)monitor_printf;
> +        print_vfunc = (error_print_vfunc)monitor_vprintf;
> +        print_opaque = cur;
> +    } else {
> +        print_func = (error_print_func)fprintf;
> +        print_vfunc = (error_print_vfunc)vfprintf;
> +        print_opaque = stderr;
> +    }

print_func is is void (*)(void *, const char *, ...).

monitor_printf() is int (*)(Monitor *, const char *, ...).

fprintf() is int (*)(FILE *, const char *, ...)

ISO/IEC 9899:1999 §6.3.2.3 Pointers:

       [#8] A pointer to a function of one type may be converted to
       a pointer to a function of another type and back again;  the
       result  shall  compare  equal to the original pointer.  If a
       converted pointer is used to call a function whose  type  is
       not  compatible  with  the  pointed-to type, the behavior is
       undefined.

For this to work in practice, three conditions need to hold:

1. Both Monitor * and FILE * arguments are passed exactly like void *
arguments.  Holds on sane machines.

2. A function returning void is called the same way as a function
returning int when the value is ignored.  Holds on sane machines.  We
can easily eliminate this condition: just change print_func from void to
int.

3. The guys writing the compiler refrain from making use of their
self-granted license to ruin our day because our program has undefined
behavior.  Since improving some SPEC benchmark by half a percent is
clearly worth breaking any number of working programs, ...

If we want to stay out of this swamp, we need to define wrapper
functions taking void * and returning it.

> +
> +    if (message_with_timestamp && !cur) {
>          timestr = real_time_iso8601();
> -        error_printf("%s ", timestr);
> +        print_func(print_opaque, "%s ", timestr);
>          g_free(timestr);
>      }
>  
>      /* Only prepend guest name if -msg guest-name and -name guest=... are set */
> -    if (error_with_guestname && error_guest_name && !monitor_cur_hmp()) {
> -        error_printf("%s ", error_guest_name);
> +    if (error_with_guestname && error_guest_name && !cur) {
> +        print_func(print_opaque, "%s ", error_guest_name);
>      }
>  
> -    print_loc();
> +    print_loc(!!cur, print_func, print_opaque);
>  
>      switch (type) {
>      case REPORT_TYPE_ERROR:
>          break;
>      case REPORT_TYPE_WARNING:
> -        error_printf("warning: ");
> +        print_func(print_opaque, "warning: ");
>          break;
>      case REPORT_TYPE_INFO:
> -        error_printf("info: ");
> +        print_func(print_opaque, "info: ");
>          break;
>      }
>  
> -    error_vprintf(fmt, ap);
> -    error_printf("\n");
> +    print_vfunc(print_opaque, fmt, ap);
> +    print_func(print_opaque, "\n");
>  }
>  
>  /*

The code becomes more complicated.  Hmm.

As long as monitor_cur() hits trace points, we really want to call it
just once, before we start printing the error message.

Calls during vreport() (in master, because I can't be bothered to
recompile):

(1) At the beginning of vreport().  Fine.

(2) In the middle of vreport().  Easy to avoid: reuse the value gotten
at (1).

(3) In print_loc().  Easy to avoid: called only by vreport(), so pass
the value gotten at (1).

(4) In error_vprintf(), called multiple times from vreport() and
print_loc() directly and via error_printf().  Obvious, stupid solution:
have error_vprintf() and error_printf() take a Monitor *argument.  But
that's no good, because we have numerous callers, and we'd rather not
change these to pass monitor_cur().  So create two new functions, and
make the existing ones wrap around them.

Thoughts?



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 07/20] util: add API to fetch the current thread name
  2025-09-10 18:03 ` [PATCH v3 07/20] util: add API to fetch the current thread name Daniel P. Berrangé
  2025-09-19  8:59   ` Markus Armbruster
@ 2025-09-23 12:12   ` Markus Armbruster
  2025-09-24  8:55     ` Daniel P. Berrangé
  1 sibling, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-23 12:12 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> This will be used to include the thread name in error reports
> in a later patch. It returns a const string stored in a thread
> local to avoid memory allocation when it is called repeatedly
> in a single thread. This makes the assumption that the thread
> name is set at the very start of the thread, which is the case
> when using qemu_thread_create.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

[...]

> diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
> index 7a734a7a09..e3789c20d1 100644
> --- a/util/qemu-thread-win32.c
> +++ b/util/qemu-thread-win32.c

[...]

> @@ -412,3 +418,38 @@ bool qemu_thread_is_self(QemuThread *thread)
>  {
>      return GetCurrentThreadId() == thread->tid;
>  }
> +
> +static __thread char namebuf[64];
> +
> +const char *qemu_thread_get_name(void)
> +{
> +    HRESULT hr;
> +    wchar_t *namew = NULL;
> +    g_autofree char *name = NULL;
> +
> +    if (namebuf[0] != '\0') {
> +        return namebuf;
> +    }
> +
> +    if (!load_thread_description()) {
> +        goto error;
> +    }
> +
> +    hr = GetThreadDescriptionFunc(GetCurrentThread(), &namew);
> +    if (!SUCCEEDED(hr)) {
> +        goto error;
> +    }
> +
> +    name = g_utf16_to_utf8(namew, -1, NULL, NULL, NULL);
> +    LocalFree(namew);
> +    if (!name) {
> +        goto error;
> +    }
> +
> +    g_strlcpy(namebuf, name, G_N_ELEMENTS(namebuf));
> +    return namebuf;
> +
> + error:
> +    strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
> +    return namebuf;
> +}

../util/qemu-thread-win32.c: In function 'qemu_thread_get_name':
../util/qemu-thread-win32.c:453:5: error: implicit declaration of function 'strlcpy'; did you mean 'strncpy'? [-Wimplicit-function-declaration]
  453 |     strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
      |     ^~~~~~~
      |     strncpy
../util/qemu-thread-win32.c:453:5: error: nested extern declaration of 'strlcpy' [-Werror=nested-externs]



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
                     ` (2 preceding siblings ...)
  2025-09-17 14:11   ` Markus Armbruster
@ 2025-09-23 12:46   ` Philippe Mathieu-Daudé
  2025-09-23 14:28   ` Markus Armbruster
  4 siblings, 0 replies; 84+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-23 12:46 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

On 10/9/25 20:03, Daniel P. Berrangé wrote:
> Some code makes multiple qemu_log calls to incrementally emit
> a single message. Currently timestamps get prepended to all
> qemu_log calls, even those continuing a previous incomplete
> message.
> 
> This changes the qemu_log so it skips adding a new line prefix,
> if the previous qemu_log call did NOT end with a newline.
> 
> Reported-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>   util/log.c | 9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp
  2025-09-10 18:03 ` [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp Daniel P. Berrangé
  2025-09-11  8:50   ` Richard Henderson
  2025-09-19 11:42   ` Markus Armbruster
@ 2025-09-23 12:48   ` Philippe Mathieu-Daudé
  2 siblings, 0 replies; 84+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-09-23 12:48 UTC (permalink / raw)
  To: Daniel P. Berrangé, qemu-devel
  Cc: qemu-block, Hanna Reitz, Kevin Wolf, Marc-André Lureau,
	Christian Schoenebeck, Richard Henderson, Manos Pitsidianakis,
	Stefan Weil, Gerd Hoffmann, Paolo Bonzini, Markus Armbruster,
	Dr. David Alan Gilbert

On 10/9/25 20:03, Daniel P. Berrangé wrote:
> These functions only had one caller which was easily converted to
> the normal error_printf() function. Remove them as they don't add
> sufficient value.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>   include/monitor/monitor.h |  3 ---
>   monitor/monitor.c         | 24 ------------------------
>   stubs/error-printf.c      |  5 -----
>   3 files changed, 32 deletions(-)

:)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
                     ` (3 preceding siblings ...)
  2025-09-23 12:46   ` Philippe Mathieu-Daudé
@ 2025-09-23 14:28   ` Markus Armbruster
  2025-09-23 14:55     ` Daniel P. Berrangé
  4 siblings, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-23 14:28 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> Some code makes multiple qemu_log calls to incrementally emit
> a single message. Currently timestamps get prepended to all
> qemu_log calls, even those continuing a previous incomplete
> message.
>
> This changes the qemu_log so it skips adding a new line prefix,
> if the previous qemu_log call did NOT end with a newline.
>
> Reported-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

This patch has kept nagging me in the back of my brain.  So I'm back for
a second look.

> ---
>  util/log.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/util/log.c b/util/log.c
> index abdcb6b311..2642a55c59 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
>      }
>  }
>  
> +/*
> + * 'true' if the previous log message lacked a trailing '\n',
> + * and thus the subsequent call must skip any prefix
> + */
> +static __thread bool incomplete;
> +
>  void qemu_log(const char *fmt, ...)
>  {
>      FILE *f;
> @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
>       * was emitted if we are delayed acquiring the
>       * mutex
>       */
> -    if (message_with_timestamp) {
> +    if (message_with_timestamp && !incomplete) {
>          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
>          timestr = g_date_time_format_iso8601(dt);
>      }
> @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
       f = qemu_log_trylock();
       if (f) {
           va_list ap;

           if (timestr) {
               fprintf(f, "%s ", timestr);
           }

>          va_start(ap, fmt);
>          vfprintf(f, fmt, ap);
>          va_end(ap);
> +        incomplete = fmt[strlen(fmt) - 1] != '\n';
>          qemu_log_unlock(f);
>      }
>  }

Two cases:

(A) Single log

    qemu_log_trylock() returns @global_file, and uses RCU to ensure it
    remains valid until qemu_log_unlock().  I think.

(B) Log split per thread (-d tid)

    qemu_log_trylock() returns thread-local @thread_file.

In addition, qemu_log_trylock() locks the FILE it returns with
flockfile(), so no other thread can write to it until qemu_log_unlock()
unlocks it with funlockfile().  This ensures the entire output of in
between stays together.

Let's see how this plays with @incomplete.

(B) Log split per thread (-d tid)

    @incomplete is thread-local.  It records wether the last qemu_log()
    in this thread was an incomplete line.  If it was, the next
    qemu_log() continues the line.  Unless something else wrote to
    @thread_file in between, but that's not supposed to happen.  Good.

(A) Single log

    All thread log to the same FILE.  Consider:

    1. Thread 1 starts.  Its @incomplete is initialized to false.

    2. Thread 2 starts.  Its @incomplete is initialized to false.

    3. Thread 1 logs "abra".  Its @incomplete is set to true.

    4. Thread 2 logs "interrupt\n".  Its @incomplete remains false.

    5. Thread 2 logs "cadbra\n".  Its @incomplete goes back to false.

    Resulting log file contents:

        PREFIX "abra" PREFIX "interrupt\n"
        "cadabra\n"

    Not good.

We could complicate this code further to mitigate.  For instance, we
could use a thread-local @incomplete for (B), and a global one for (A).
This ensures log lines start with PREFIX as they should, but does
nothing to avoid mixing up line parts from different threads.  My
example would then produce

        PREFIX "abrainterrupt\n"
        PREFIX "cababra\n"

My take: "Doctor, it hurts when I do that!"  "Don't do that then."
Logging incomplete lines with qemu_log() can hurt.  Don't do that then.



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-23 14:28   ` Markus Armbruster
@ 2025-09-23 14:55     ` Daniel P. Berrangé
  2025-09-24  7:06       ` Markus Armbruster
  0 siblings, 1 reply; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-23 14:55 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Tue, Sep 23, 2025 at 04:28:42PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > Some code makes multiple qemu_log calls to incrementally emit
> > a single message. Currently timestamps get prepended to all
> > qemu_log calls, even those continuing a previous incomplete
> > message.
> >
> > This changes the qemu_log so it skips adding a new line prefix,
> > if the previous qemu_log call did NOT end with a newline.
> >
> > Reported-by: Richard Henderson <richard.henderson@linaro.org>
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> 
> This patch has kept nagging me in the back of my brain.  So I'm back for
> a second look.
> 
> > ---
> >  util/log.c | 9 ++++++++-
> >  1 file changed, 8 insertions(+), 1 deletion(-)
> >
> > diff --git a/util/log.c b/util/log.c
> > index abdcb6b311..2642a55c59 100644
> > --- a/util/log.c
> > +++ b/util/log.c
> > @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
> >      }
> >  }
> >  
> > +/*
> > + * 'true' if the previous log message lacked a trailing '\n',
> > + * and thus the subsequent call must skip any prefix
> > + */
> > +static __thread bool incomplete;
> > +
> >  void qemu_log(const char *fmt, ...)
> >  {
> >      FILE *f;
> > @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
> >       * was emitted if we are delayed acquiring the
> >       * mutex
> >       */
> > -    if (message_with_timestamp) {
> > +    if (message_with_timestamp && !incomplete) {
> >          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
> >          timestr = g_date_time_format_iso8601(dt);
> >      }
> > @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
>        f = qemu_log_trylock();
>        if (f) {
>            va_list ap;
> 
>            if (timestr) {
>                fprintf(f, "%s ", timestr);
>            }
> 
> >          va_start(ap, fmt);
> >          vfprintf(f, fmt, ap);
> >          va_end(ap);
> > +        incomplete = fmt[strlen(fmt) - 1] != '\n';
> >          qemu_log_unlock(f);
> >      }
> >  }
> 
> Two cases:
> 
> (A) Single log
> 
>     qemu_log_trylock() returns @global_file, and uses RCU to ensure it
>     remains valid until qemu_log_unlock().  I think.
> 
> (B) Log split per thread (-d tid)
> 
>     qemu_log_trylock() returns thread-local @thread_file.
> 
> In addition, qemu_log_trylock() locks the FILE it returns with
> flockfile(), so no other thread can write to it until qemu_log_unlock()
> unlocks it with funlockfile().  This ensures the entire output of in
> between stays together.
> 
> Let's see how this plays with @incomplete.
> 
> (B) Log split per thread (-d tid)
> 
>     @incomplete is thread-local.  It records wether the last qemu_log()
>     in this thread was an incomplete line.  If it was, the next
>     qemu_log() continues the line.  Unless something else wrote to
>     @thread_file in between, but that's not supposed to happen.  Good.
> 
> (A) Single log
> 
>     All thread log to the same FILE.  Consider:
> 
>     1. Thread 1 starts.  Its @incomplete is initialized to false.
> 
>     2. Thread 2 starts.  Its @incomplete is initialized to false.
> 
>     3. Thread 1 logs "abra".  Its @incomplete is set to true.
> 
>     4. Thread 2 logs "interrupt\n".  Its @incomplete remains false.
> 
>     5. Thread 2 logs "cadbra\n".  Its @incomplete goes back to false.
> 
>     Resulting log file contents:
> 
>         PREFIX "abra" PREFIX "interrupt\n"
>         "cadabra\n"
> 
>     Not good.
> 
> We could complicate this code further to mitigate.  For instance, we
> could use a thread-local @incomplete for (B), and a global one for (A).
> This ensures log lines start with PREFIX as they should, but does
> nothing to avoid mixing up line parts from different threads.  My
> example would then produce
> 
>         PREFIX "abrainterrupt\n"
>         PREFIX "cababra\n"
> 
> My take: "Doctor, it hurts when I do that!"  "Don't do that then."
> Logging incomplete lines with qemu_log() can hurt.  Don't do that then.

I just took a look at linux-user/syscall.c as that is one place that
heavily uses qemu_log() for incomplete lines.

What I didn't realize was that the expectation is to call
qemu_log_trylock() (which returns the "FILE *" target) and
then you can ignore the "FILE *" and just call qemu_log()
repeatedly, and finally call qemu_log_unlock(FILE *) when
done.

https://gitlab.com/qemu-project/qemu/-/blob/master/linux-user/strace.c?ref_type=heads#L4396

This is a slightly wierd API design, but that seems to be
the intended way to serailize and in that context, my
patch/hack here will be sufficiently good.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-23 14:55     ` Daniel P. Berrangé
@ 2025-09-24  7:06       ` Markus Armbruster
  2025-09-24  7:12         ` Daniel P. Berrangé
                           ` (2 more replies)
  0 siblings, 3 replies; 84+ messages in thread
From: Markus Armbruster @ 2025-09-24  7:06 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Tue, Sep 23, 2025 at 04:28:42PM +0200, Markus Armbruster wrote:
>> Daniel P. Berrangé <berrange@redhat.com> writes:
>> 
>> > Some code makes multiple qemu_log calls to incrementally emit
>> > a single message. Currently timestamps get prepended to all
>> > qemu_log calls, even those continuing a previous incomplete
>> > message.
>> >
>> > This changes the qemu_log so it skips adding a new line prefix,
>> > if the previous qemu_log call did NOT end with a newline.
>> >
>> > Reported-by: Richard Henderson <richard.henderson@linaro.org>
>> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
>> 
>> This patch has kept nagging me in the back of my brain.  So I'm back for
>> a second look.
>> 
>> > ---
>> >  util/log.c | 9 ++++++++-
>> >  1 file changed, 8 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/util/log.c b/util/log.c
>> > index abdcb6b311..2642a55c59 100644
>> > --- a/util/log.c
>> > +++ b/util/log.c
>> > @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
>> >      }
>> >  }
>> >  
>> > +/*
>> > + * 'true' if the previous log message lacked a trailing '\n',
>> > + * and thus the subsequent call must skip any prefix
>> > + */
>> > +static __thread bool incomplete;
>> > +
>> >  void qemu_log(const char *fmt, ...)
>> >  {
>> >      FILE *f;
>> > @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
>> >       * was emitted if we are delayed acquiring the
>> >       * mutex
>> >       */
>> > -    if (message_with_timestamp) {
>> > +    if (message_with_timestamp && !incomplete) {
>> >          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
>> >          timestr = g_date_time_format_iso8601(dt);
>> >      }
>> > @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
>>        f = qemu_log_trylock();
>>        if (f) {
>>            va_list ap;
>> 
>>            if (timestr) {
>>                fprintf(f, "%s ", timestr);
>>            }
>> 
>> >          va_start(ap, fmt);
>> >          vfprintf(f, fmt, ap);
>> >          va_end(ap);
>> > +        incomplete = fmt[strlen(fmt) - 1] != '\n';
>> >          qemu_log_unlock(f);
>> >      }
>> >  }
>> 
>> Two cases:
>> 
>> (A) Single log
>> 
>>     qemu_log_trylock() returns @global_file, and uses RCU to ensure it
>>     remains valid until qemu_log_unlock().  I think.
>> 
>> (B) Log split per thread (-d tid)
>> 
>>     qemu_log_trylock() returns thread-local @thread_file.
>> 
>> In addition, qemu_log_trylock() locks the FILE it returns with
>> flockfile(), so no other thread can write to it until qemu_log_unlock()
>> unlocks it with funlockfile().  This ensures the entire output of in
>> between stays together.
>> 
>> Let's see how this plays with @incomplete.
>> 
>> (B) Log split per thread (-d tid)
>> 
>>     @incomplete is thread-local.  It records wether the last qemu_log()
>>     in this thread was an incomplete line.  If it was, the next
>>     qemu_log() continues the line.  Unless something else wrote to
>>     @thread_file in between, but that's not supposed to happen.  Good.
>> 
>> (A) Single log
>> 
>>     All thread log to the same FILE.  Consider:
>> 
>>     1. Thread 1 starts.  Its @incomplete is initialized to false.
>> 
>>     2. Thread 2 starts.  Its @incomplete is initialized to false.
>> 
>>     3. Thread 1 logs "abra".  Its @incomplete is set to true.
>> 
>>     4. Thread 2 logs "interrupt\n".  Its @incomplete remains false.
>> 
>>     5. Thread 2 logs "cadbra\n".  Its @incomplete goes back to false.
>> 
>>     Resulting log file contents:
>> 
>>         PREFIX "abra" PREFIX "interrupt\n"
>>         "cadabra\n"
>> 
>>     Not good.
>> 
>> We could complicate this code further to mitigate.  For instance, we
>> could use a thread-local @incomplete for (B), and a global one for (A).
>> This ensures log lines start with PREFIX as they should, but does
>> nothing to avoid mixing up line parts from different threads.  My
>> example would then produce
>> 
>>         PREFIX "abrainterrupt\n"
>>         PREFIX "cababra\n"
>> 
>> My take: "Doctor, it hurts when I do that!"  "Don't do that then."
>> Logging incomplete lines with qemu_log() can hurt.  Don't do that then.
>
> I just took a look at linux-user/syscall.c as that is one place that
> heavily uses qemu_log() for incomplete lines.
>
> What I didn't realize was that the expectation is to call
> qemu_log_trylock() (which returns the "FILE *" target) and
> then you can ignore the "FILE *" and just call qemu_log()
> repeatedly, and finally call qemu_log_unlock(FILE *) when
> done.
>
> https://gitlab.com/qemu-project/qemu/-/blob/master/linux-user/strace.c?ref_type=heads#L4396

I can see the qemu_log_trylock() / qemu_log_unlock() bracket.  But the
code within doesn't work the way you describe: it uses fprintf(f, ...).

If it did ignore @f and call qemu_log(), qemu_log() would
qemu_log_trylock() again, taking the RCU read lock and the flockfile()
lock on @f recursively.  Should work.

> This is a slightly wierd API design,

More seriously: entirely undocumented.  The only hint is the presence of
qemu_log_trylock() and qemu_log_unlock().

>                                      but that seems to be
> the intended way to serailize and in that context, my
> patch/hack here will be sufficiently good.

Right, the flockfile() locks out the other thread.


I feel this is more complex than it ought to be.  It also lacks comments
explaining the locking.

On a green field, I'd make the logging function append a newline.  When
the line to be logged is to be built up with multiple printf-like calls,
use g_string_printf().  If you're worried about reallocations, use
something like g_string_sized_new(512).  Log lines longer than that
would be masochism anyway.  If even that single allocation bothers you,
build your logging around fixed thread-local buffers, avoiding stdio.


No objection to your patch.  It digs us deeper into this hole, but we
got worse holes to worry about.



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-24  7:06       ` Markus Armbruster
@ 2025-09-24  7:12         ` Daniel P. Berrangé
  2025-09-24  9:20         ` Daniel P. Berrangé
  2025-09-24 12:34         ` Markus Armbruster
  2 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-24  7:12 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Wed, Sep 24, 2025 at 09:06:55AM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > On Tue, Sep 23, 2025 at 04:28:42PM +0200, Markus Armbruster wrote:
> >> Daniel P. Berrangé <berrange@redhat.com> writes:
> >> 
> >> > Some code makes multiple qemu_log calls to incrementally emit
> >> > a single message. Currently timestamps get prepended to all
> >> > qemu_log calls, even those continuing a previous incomplete
> >> > message.
> >> >
> >> > This changes the qemu_log so it skips adding a new line prefix,
> >> > if the previous qemu_log call did NOT end with a newline.
> >> >
> >> > Reported-by: Richard Henderson <richard.henderson@linaro.org>
> >> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> >> 
> >> This patch has kept nagging me in the back of my brain.  So I'm back for
> >> a second look.
> >> 
> >> > ---
> >> >  util/log.c | 9 ++++++++-
> >> >  1 file changed, 8 insertions(+), 1 deletion(-)
> >> >
> >> > diff --git a/util/log.c b/util/log.c
> >> > index abdcb6b311..2642a55c59 100644
> >> > --- a/util/log.c
> >> > +++ b/util/log.c
> >> > @@ -143,6 +143,12 @@ void qemu_log_unlock(FILE *logfile)
> >> >      }
> >> >  }
> >> >  
> >> > +/*
> >> > + * 'true' if the previous log message lacked a trailing '\n',
> >> > + * and thus the subsequent call must skip any prefix
> >> > + */
> >> > +static __thread bool incomplete;
> >> > +
> >> >  void qemu_log(const char *fmt, ...)
> >> >  {
> >> >      FILE *f;
> >> > @@ -154,7 +160,7 @@ void qemu_log(const char *fmt, ...)
> >> >       * was emitted if we are delayed acquiring the
> >> >       * mutex
> >> >       */
> >> > -    if (message_with_timestamp) {
> >> > +    if (message_with_timestamp && !incomplete) {
> >> >          g_autoptr(GDateTime) dt = g_date_time_new_now_utc();
> >> >          timestr = g_date_time_format_iso8601(dt);
> >> >      }
> >> > @@ -170,6 +176,7 @@ void qemu_log(const char *fmt, ...)
> >>        f = qemu_log_trylock();
> >>        if (f) {
> >>            va_list ap;
> >> 
> >>            if (timestr) {
> >>                fprintf(f, "%s ", timestr);
> >>            }
> >> 
> >> >          va_start(ap, fmt);
> >> >          vfprintf(f, fmt, ap);
> >> >          va_end(ap);
> >> > +        incomplete = fmt[strlen(fmt) - 1] != '\n';
> >> >          qemu_log_unlock(f);
> >> >      }
> >> >  }
> >> 
> >> Two cases:
> >> 
> >> (A) Single log
> >> 
> >>     qemu_log_trylock() returns @global_file, and uses RCU to ensure it
> >>     remains valid until qemu_log_unlock().  I think.
> >> 
> >> (B) Log split per thread (-d tid)
> >> 
> >>     qemu_log_trylock() returns thread-local @thread_file.
> >> 
> >> In addition, qemu_log_trylock() locks the FILE it returns with
> >> flockfile(), so no other thread can write to it until qemu_log_unlock()
> >> unlocks it with funlockfile().  This ensures the entire output of in
> >> between stays together.
> >> 
> >> Let's see how this plays with @incomplete.
> >> 
> >> (B) Log split per thread (-d tid)
> >> 
> >>     @incomplete is thread-local.  It records wether the last qemu_log()
> >>     in this thread was an incomplete line.  If it was, the next
> >>     qemu_log() continues the line.  Unless something else wrote to
> >>     @thread_file in between, but that's not supposed to happen.  Good.
> >> 
> >> (A) Single log
> >> 
> >>     All thread log to the same FILE.  Consider:
> >> 
> >>     1. Thread 1 starts.  Its @incomplete is initialized to false.
> >> 
> >>     2. Thread 2 starts.  Its @incomplete is initialized to false.
> >> 
> >>     3. Thread 1 logs "abra".  Its @incomplete is set to true.
> >> 
> >>     4. Thread 2 logs "interrupt\n".  Its @incomplete remains false.
> >> 
> >>     5. Thread 2 logs "cadbra\n".  Its @incomplete goes back to false.
> >> 
> >>     Resulting log file contents:
> >> 
> >>         PREFIX "abra" PREFIX "interrupt\n"
> >>         "cadabra\n"
> >> 
> >>     Not good.
> >> 
> >> We could complicate this code further to mitigate.  For instance, we
> >> could use a thread-local @incomplete for (B), and a global one for (A).
> >> This ensures log lines start with PREFIX as they should, but does
> >> nothing to avoid mixing up line parts from different threads.  My
> >> example would then produce
> >> 
> >>         PREFIX "abrainterrupt\n"
> >>         PREFIX "cababra\n"
> >> 
> >> My take: "Doctor, it hurts when I do that!"  "Don't do that then."
> >> Logging incomplete lines with qemu_log() can hurt.  Don't do that then.
> >
> > I just took a look at linux-user/syscall.c as that is one place that
> > heavily uses qemu_log() for incomplete lines.
> >
> > What I didn't realize was that the expectation is to call
> > qemu_log_trylock() (which returns the "FILE *" target) and
> > then you can ignore the "FILE *" and just call qemu_log()
> > repeatedly, and finally call qemu_log_unlock(FILE *) when
> > done.
> >
> > https://gitlab.com/qemu-project/qemu/-/blob/master/linux-user/strace.c?ref_type=heads#L4396
> 
> I can see the qemu_log_trylock() / qemu_log_unlock() bracket.  But the
> code within doesn't work the way you describe: it uses fprintf(f, ...).
> If it did ignore @f and call qemu_log(), qemu_log() would
> qemu_log_trylock() again, taking the RCU read lock and the flockfile()
> lock on @f recursively.  Should work.


Only the fallback path (the 'else' branch) uses fprintf.

The main path is doing

 scnames[i].call(cpu_env, &scnames[i], arg1, arg2, arg3,
                                arg4, arg5, arg6);

which calls out to the other countless 'print_XXXX' methods,
one per syscall, which all use qemu_log().


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 04/20] util: expose qemu_thread_set_name
  2025-09-19  8:39   ` Markus Armbruster
@ 2025-09-24  8:37     ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-24  8:37 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Fri, Sep 19, 2025 at 10:39:31AM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > The ability to set the thread name needs to be used in a number
> > of places, so expose the current impls as public methods.
> >
> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> > Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  include/qemu/thread.h    |  1 +
> >  util/qemu-thread-posix.c | 30 ++++++++++++++++++------------
> >  util/qemu-thread-win32.c |  6 +++---
> >  3 files changed, 22 insertions(+), 15 deletions(-)
> >
> > diff --git a/include/qemu/thread.h b/include/qemu/thread.h
> > index 3a286bb3ef..27b888ab0a 100644
> > --- a/include/qemu/thread.h
> > +++ b/include/qemu/thread.h
> > @@ -215,6 +215,7 @@ void *qemu_thread_join(QemuThread *thread);
> >  void qemu_thread_get_self(QemuThread *thread);
> >  bool qemu_thread_is_self(QemuThread *thread);
> >  G_NORETURN void qemu_thread_exit(void *retval);
> > +void qemu_thread_set_name(const char *name);
> >  
> >  struct Notifier;
> >  /**
> > diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
> > index 7c985b5d38..ddaa1de4dd 100644
> > --- a/util/qemu-thread-posix.c
> > +++ b/util/qemu-thread-posix.c
> > @@ -329,6 +329,21 @@ static void qemu_thread_atexit_notify(void *arg)
> >      notifier_list_notify(&thread_exit, NULL);
> >  }
> >  
> > +void qemu_thread_set_name(const char *name)
> > +{
> > +    /*
> > +     * Attempt to set the threads name; note that this is for debug, so
> > +     * we're not going to fail if we can't set it.
> > +     */
> > +# if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> > +    pthread_setname_np(pthread_self(), name);
> > +# elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
> > +    pthread_setname_np(name);
> > +# elif defined(CONFIG_PTHREAD_SET_NAME_NP)
> > +    pthread_set_name_np(pthread_self(), name);
> > +# endif
> > +}
> > +
> >  typedef struct {
> >      void *(*start_routine)(void *);
> >      void *arg;
> > @@ -342,20 +357,11 @@ static void *qemu_thread_start(void *args)
> >      void *arg = qemu_thread_args->arg;
> >      void *r;
> >  
> > -    /* Attempt to set the threads name; note that this is for debug, so
> > -     * we're not going to fail if we can't set it.
> > -     */
> >      if (qemu_thread_args->name) {
> > -# if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
> > -        pthread_setname_np(pthread_self(), qemu_thread_args->name);
> > -# elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
> > -        pthread_setname_np(qemu_thread_args->name);
> > -# elif defined(CONFIG_PTHREAD_SET_NAME_NP)
> > -        pthread_set_name_np(pthread_self(), qemu_thread_args->name);
> > -# endif
> > +        qemu_thread_set_name(qemu_thread_args->name);
> 
> Clean factoring out up to here.
> 
> > +        QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
> > +        g_free(qemu_thread_args->name);
> >      }
> > -    QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
> > -    g_free(qemu_thread_args->name);
> 
> This part avoids
> 
>        QEMU_TSAN_ANNOTATE_THREAD_NAME(NULL);
>        g_free(NULL);
> 
> The latter is an obvious no-op.  The former isn't.  Separate patch or
> mention in the commit message?

I'll just drop this since it isn't needed by the patch

> 
> >      g_free(qemu_thread_args);
> >  
> >      /*
> > diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
> > index 9595a5b090..62eaa11026 100644
> > --- a/util/qemu-thread-win32.c
> > +++ b/util/qemu-thread-win32.c
> > @@ -316,7 +316,7 @@ void *qemu_thread_join(QemuThread *thread)
> >      return ret;
> >  }
> >  
> > -static void set_thread_description(HANDLE h, const char *name)
> > +void qemu_thread_set_name(const char *name)
> >  {
> >      g_autofree wchar_t *namew = NULL;
> >  
> > @@ -329,7 +329,7 @@ static void set_thread_description(HANDLE h, const char *name)
> >          return;
> >      }
> >  
> > -    SetThreadDescriptionFunc(h, namew);
> > +    SetThreadDescriptionFunc(GetCurrentThread(), namew);
> >  }
> >  
> >  void qemu_thread_create(QemuThread *thread, const char *name,
> > @@ -356,7 +356,7 @@ void qemu_thread_create(QemuThread *thread, const char *name,
>        hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
>                                          data, 0, &thread->tid);
>        if (!hThread) {
> >          error_exit(GetLastError(), __func__);
> >      }
> >      if (name) {
> > -        set_thread_description(hThread, name);
> > +        qemu_thread_set_name(name);
> >      }
> >      CloseHandle(hThread);
> 
> This changes the first argument of SetThreadDescriptionFunc() from the
> value of _beginthreadex() to GetCurrentThread().  I'm a happy Windows
> ignoramus...  sure these refer to the same thread?

No, I messed up here. I should have moved the qemu_thread_set_name call
into the thread function, as this is still the parent thread.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 07/20] util: add API to fetch the current thread name
  2025-09-23 12:12   ` Markus Armbruster
@ 2025-09-24  8:55     ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-24  8:55 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Tue, Sep 23, 2025 at 02:12:02PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > This will be used to include the thread name in error reports
> > in a later patch. It returns a const string stored in a thread
> > local to avoid memory allocation when it is called repeatedly
> > in a single thread. This makes the assumption that the thread
> > name is set at the very start of the thread, which is the case
> > when using qemu_thread_create.
> >
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> 
> [...]
> 
> > diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
> > index 7a734a7a09..e3789c20d1 100644
> > --- a/util/qemu-thread-win32.c
> > +++ b/util/qemu-thread-win32.c
> 
> [...]
> 
> > @@ -412,3 +418,38 @@ bool qemu_thread_is_self(QemuThread *thread)
> >  {
> >      return GetCurrentThreadId() == thread->tid;
> >  }
> > +
> > +static __thread char namebuf[64];
> > +
> > +const char *qemu_thread_get_name(void)
> > +{
> > +    HRESULT hr;
> > +    wchar_t *namew = NULL;
> > +    g_autofree char *name = NULL;
> > +
> > +    if (namebuf[0] != '\0') {
> > +        return namebuf;
> > +    }
> > +
> > +    if (!load_thread_description()) {
> > +        goto error;
> > +    }
> > +
> > +    hr = GetThreadDescriptionFunc(GetCurrentThread(), &namew);
> > +    if (!SUCCEEDED(hr)) {
> > +        goto error;
> > +    }
> > +
> > +    name = g_utf16_to_utf8(namew, -1, NULL, NULL, NULL);
> > +    LocalFree(namew);
> > +    if (!name) {
> > +        goto error;
> > +    }
> > +
> > +    g_strlcpy(namebuf, name, G_N_ELEMENTS(namebuf));
> > +    return namebuf;
> > +
> > + error:
> > +    strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
> > +    return namebuf;
> > +}
> 
> ../util/qemu-thread-win32.c: In function 'qemu_thread_get_name':
> ../util/qemu-thread-win32.c:453:5: error: implicit declaration of function 'strlcpy'; did you mean 'strncpy'? [-Wimplicit-function-declaration]
>   453 |     strlcpy(namebuf, "unnamed", G_N_ELEMENTS(namebuf));
>       |     ^~~~~~~
>       |     strncpy
> ../util/qemu-thread-win32.c:453:5: error: nested extern declaration of 'strlcpy' [-Werror=nested-externs]

Sigh, I meant g_strlcopy like the line shortly before.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-24  7:06       ` Markus Armbruster
  2025-09-24  7:12         ` Daniel P. Berrangé
@ 2025-09-24  9:20         ` Daniel P. Berrangé
  2025-09-24 12:34         ` Markus Armbruster
  2 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-24  9:20 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Wed, Sep 24, 2025 at 09:06:55AM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> 
> > On Tue, Sep 23, 2025 at 04:28:42PM +0200, Markus Armbruster wrote:
> >> Daniel P. Berrangé <berrange@redhat.com> writes:
> >> 
> >> > Some code makes multiple qemu_log calls to incrementally emit
> >> > a single message. Currently timestamps get prepended to all
> >> > qemu_log calls, even those continuing a previous incomplete
> >> > message.
> >> >
> >> > This changes the qemu_log so it skips adding a new line prefix,
> >> > if the previous qemu_log call did NOT end with a newline.
> >> >
> >> > Reported-by: Richard Henderson <richard.henderson@linaro.org>
> >> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

snip

> > What I didn't realize was that the expectation is to call
> > qemu_log_trylock() (which returns the "FILE *" target) and
> > then you can ignore the "FILE *" and just call qemu_log()
> > repeatedly, and finally call qemu_log_unlock(FILE *) when
> > done.
> >
> > https://gitlab.com/qemu-project/qemu/-/blob/master/linux-user/strace.c?ref_type=heads#L4396
> 
> I can see the qemu_log_trylock() / qemu_log_unlock() bracket.  But the
> code within doesn't work the way you describe: it uses fprintf(f, ...).
> 
> If it did ignore @f and call qemu_log(), qemu_log() would
> qemu_log_trylock() again, taking the RCU read lock and the flockfile()
> lock on @f recursively.  Should work.
> 
> > This is a slightly wierd API design,
> 
> More seriously: entirely undocumented.  The only hint is the presence of
> qemu_log_trylock() and qemu_log_unlock().

I'm including a new patch that starts some API docs for the
log APIs.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-24  7:06       ` Markus Armbruster
  2025-09-24  7:12         ` Daniel P. Berrangé
  2025-09-24  9:20         ` Daniel P. Berrangé
@ 2025-09-24 12:34         ` Markus Armbruster
  2025-09-24 13:30           ` Daniel P. Berrangé
  2 siblings, 1 reply; 84+ messages in thread
From: Markus Armbruster @ 2025-09-24 12:34 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

Pondering the interleave between logging and error reporting led me to
an interleave between error reporting and itself.

vreport() prints a single line to stderr in several parts:

* Timestamp (if enabled)

* Guest name (if enabled)

* Program name

* Location (if there is one)

* Message type

* Message text

* Newline

Stdio guarantees that each part comes out as a whole even when other
threads print to the same FILE at the same time.  But another thread's
print output can still squeeze in between parts.  Unlikely, but
possible.  To avoid it, we'd need to guard vreport()'s printing with
flockfile() ... funlockfile().

Thoughts?



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls
  2025-09-24 12:34         ` Markus Armbruster
@ 2025-09-24 13:30           ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-24 13:30 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, qemu-block, Hanna Reitz, Kevin Wolf,
	Marc-André Lureau, Christian Schoenebeck, Richard Henderson,
	Manos Pitsidianakis, Stefan Weil, Philippe Mathieu-Daudé,
	Gerd Hoffmann, Paolo Bonzini, Dr. David Alan Gilbert

On Wed, Sep 24, 2025 at 02:34:30PM +0200, Markus Armbruster wrote:
> Pondering the interleave between logging and error reporting led me to
> an interleave between error reporting and itself.
> 
> vreport() prints a single line to stderr in several parts:
> 
> * Timestamp (if enabled)
> 
> * Guest name (if enabled)
> 
> * Program name
> 
> * Location (if there is one)
> 
> * Message type
> 
> * Message text
> 
> * Newline
> 
> Stdio guarantees that each part comes out as a whole even when other
> threads print to the same FILE at the same time.  But another thread's
> print output can still squeeze in between parts.  Unlikely, but
> possible.  To avoid it, we'd need to guard vreport()'s printing with
> flockfile() ... funlockfile().
> 
> Thoughts?

You are totally correct. The qemu_log code will do the right thing
with flockfile /funlockfile, but we're missing that serialization
in the error report code. It doesn't matter quite as much as logging,
since much of time when error_report is used, it is in a scenario
that is likely to either be serialized, or be about to call exit/
abort. None the less I'm sure we can come up with real world
scenarios where error report will be concurrent in QEMU that can
interleave, so we should add the flockfile usage.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function
  2025-09-22  8:38           ` Markus Armbruster
@ 2025-09-24 16:09             ` Daniel P. Berrangé
  0 siblings, 0 replies; 84+ messages in thread
From: Daniel P. Berrangé @ 2025-09-24 16:09 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Dr. David Alan Gilbert, qemu-devel, qemu-block, Hanna Reitz,
	Kevin Wolf, Marc-André Lureau, Christian Schoenebeck,
	Richard Henderson, Manos Pitsidianakis, Stefan Weil,
	Philippe Mathieu-Daudé, Gerd Hoffmann, Paolo Bonzini

On Mon, Sep 22, 2025 at 10:38:59AM +0200, Markus Armbruster wrote:
> "Dr. David Alan Gilbert" <dave@treblig.org> writes:
> 
> > * Markus Armbruster (armbru@redhat.com) wrote:
> >> Daniel P. Berrangé <berrange@redhat.com> writes:
> >> 
> >> > On Fri, Sep 19, 2025 at 02:43:41PM +0200, Markus Armbruster wrote:
> >> >> Daniel P. Berrangé <berrange@redhat.com> writes:
> >> >> 
> >> >> > A number of callers use monitor_cur() followed by !monitor_cur_is_qmp().
> >> >> 
> >> >> "A number of"?  I can see just one:
> >> >> 
> >> >>     int error_vprintf(const char *fmt, va_list ap)
> >> >>     {
> >> >>         Monitor *cur_mon = monitor_cur();
> >> >> 
> >> >>         if (cur_mon && !monitor_cur_is_qmp()) {
> >> >>             return monitor_vprintf(cur_mon, fmt, ap);
> >> >>         }
> >> >>         return vfprintf(stderr, fmt, ap);
> >> >>     }
> >> >
> >> > Opps, that'll be referring to the other use of monitor_cur() in my
> >> > patches that I then removed when I re-ordered the series.
> >> >
> >> >> 
> >> >> > This is undesirable because monitor_cur_is_qmp() will itself call
> >> >> > monitor_cur() again, and monitor_cur() must acquire locks and do
> >> >> > hash table lookups. Introducing a monitor_cur_hmp() helper will
> >> >> > combine the two operations into one reducing cost.
> >> 
> >> I think the actual interface flaw is having monitor_cur_is_qmp().
> >> 
> >> In master, monitor_cur_is_qmp() is only used in monitor/monitor.c.  Both
> >> call sites have the value of monitor_cur() available as @cur_mon.
> >> They'd be better off calling monitor_is_qmp(cur_mon).
> >> 
> >> Note that in master nothing outside monitor/ cares whether a monitor is
> >> QMP or HMP.  I like that.
> >> 
> >> Your series doesn't preserve this property.
> >> 
> >> You move the first call site error_vprintf() from monitor/monitor.c to
> >> util/error-report.c in PATCH 11.  QMP vs. HMP is no longer encapsulated.
> >> Slighly irksome.
> >
> > How about a slightly simpler approach, looking above we have:
> >
> >> >>         if (cur_mon && !monitor_cur_is_qmp()) {
> >> >>             return monitor_vprintf(cur_mon, fmt, ap);
> >> >>         }
> >> >>         return vfprintf(stderr, fmt, ap);
> >
> > I think we could replace this with:
> >
> >   ret = monitor_vprintf(cur_mon, fmt, ap);
> >   if (ret == -1) {
> >        ret = vfprintf(stderr, fmt, ap);
> >   }
> >   return ret;
> >
> > monitor_vprintf already -1 exits if !mon or monitor_is_qmp(mon)
> >
> > Keeps the encapsulation, and is now 'print via the monitor but if it
> > can't do it, use printf'
> 
> monitor_printf() fails when passed a null monitor[*] or a QMP monitor.
> Reporting the error to stderr then is probably better than swallowing
> it.  Same if the function somehow picks up more failure modes.
> 
> I like it.

I've tried this and it works nicely and helps me with some other
aspects too.

> One could perhaps object that it makes "report to HMP or else stderr"
> less obvious if you don't already know that monitor_vprintf() only
> prints to HMP.  I'm okay with that.

'error_vprintf()' itself is already non-obvious, as you'd never
guess it implied any interaction with the monitor at all :-)
A little comment clarifies things sufficiently well.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 84+ messages in thread

end of thread, other threads:[~2025-09-24 16:11 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-10 18:03 [PATCH v3 00/20] util: sync error_report & qemu_log output more closely Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 01/20] include: define constant for early constructor priority Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 02/20] monitor: initialize global data from a constructor Daniel P. Berrangé
2025-09-17 14:07   ` Markus Armbruster
2025-09-17 15:31     ` Daniel P. Berrangé
2025-09-18  6:30       ` Markus Armbruster
2025-09-10 18:03 ` [PATCH v3 03/20] system: unconditionally enable thread naming Daniel P. Berrangé
2025-09-11 12:18   ` Ján Tomko
2025-09-19  8:20   ` Markus Armbruster
2025-09-19 13:32     ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 04/20] util: expose qemu_thread_set_name Daniel P. Berrangé
2025-09-19  8:39   ` Markus Armbruster
2025-09-24  8:37     ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 05/20] audio: make jackaudio use qemu_thread_set_name Daniel P. Berrangé
2025-09-11 13:21   ` Christian Schoenebeck
2025-09-12 14:58     ` Daniel P. Berrangé
2025-09-19  8:46       ` Markus Armbruster
2025-09-10 18:03 ` [PATCH v3 06/20] util: set the name for the 'main' thread Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 07/20] util: add API to fetch the current thread name Daniel P. Berrangé
2025-09-19  8:59   ` Markus Armbruster
2025-09-19  9:05     ` Daniel P. Berrangé
2025-09-19 11:35       ` Markus Armbruster
2025-09-23 12:12   ` Markus Armbruster
2025-09-24  8:55     ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 08/20] log: avoid repeated prefix on incremental qemu_log calls Daniel P. Berrangé
2025-09-10 23:20   ` Dr. David Alan Gilbert
2025-09-11  8:49   ` Richard Henderson
2025-09-17 14:11   ` Markus Armbruster
2025-09-17 15:33     ` Daniel P. Berrangé
2025-09-23 12:46   ` Philippe Mathieu-Daudé
2025-09-23 14:28   ` Markus Armbruster
2025-09-23 14:55     ` Daniel P. Berrangé
2025-09-24  7:06       ` Markus Armbruster
2025-09-24  7:12         ` Daniel P. Berrangé
2025-09-24  9:20         ` Daniel P. Berrangé
2025-09-24 12:34         ` Markus Armbruster
2025-09-24 13:30           ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 09/20] ui/vnc: remove use of error_printf_unless_qmp() Daniel P. Berrangé
2025-09-11  0:08   ` Dr. David Alan Gilbert
2025-09-11  8:51   ` Richard Henderson
2025-09-11 17:54   ` Richard Henderson
2025-09-12 15:11     ` Daniel P. Berrangé
2025-09-19 11:42       ` Markus Armbruster
2025-09-10 18:03 ` [PATCH v3 10/20] monitor: remove redundant error_[v]printf_unless_qmp Daniel P. Berrangé
2025-09-11  8:50   ` Richard Henderson
2025-09-19 11:42   ` Markus Armbruster
2025-09-23 12:48   ` Philippe Mathieu-Daudé
2025-09-10 18:03 ` [PATCH v3 11/20] monitor: move error_vprintf() back to error-report.c Daniel P. Berrangé
2025-09-11  8:55   ` Richard Henderson
2025-09-19 12:27   ` Markus Armbruster
2025-09-19 13:43     ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 12/20] monitor: introduce monitor_cur_hmp() function Daniel P. Berrangé
2025-09-11 17:52   ` Richard Henderson
2025-09-19 12:43   ` Markus Armbruster
2025-09-19 13:29     ` Daniel P. Berrangé
2025-09-20  7:06       ` Markus Armbruster
2025-09-20 11:54         ` Dr. David Alan Gilbert
2025-09-22  8:38           ` Markus Armbruster
2025-09-24 16:09             ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 13/20] util: don't skip error prefixes when QMP is active Daniel P. Berrangé
2025-09-22  8:43   ` Markus Armbruster
2025-09-10 18:03 ` [PATCH v3 14/20] util: fix interleaving of error & trace output Daniel P. Berrangé
2025-09-11 18:01   ` Richard Henderson
2025-09-11 18:05   ` Richard Henderson
2025-09-12 16:30     ` Daniel P. Berrangé
2025-09-22 12:16   ` Markus Armbruster
2025-09-10 18:03 ` [PATCH v3 15/20] util: introduce common helper for error-report & log code Daniel P. Berrangé
2025-09-11 18:02   ` Richard Henderson
2025-09-10 18:03 ` [PATCH v3 16/20] util: convert error-report & log to message API for timestamp Daniel P. Berrangé
2025-09-11 18:04   ` Richard Henderson
2025-09-10 18:03 ` [PATCH v3 17/20] util: add support for formatting a workload name in messages Daniel P. Berrangé
2025-09-11 18:06   ` Richard Henderson
2025-09-11 20:27   ` Dr. David Alan Gilbert
2025-09-12  8:34     ` Daniel P. Berrangé
2025-09-12 11:18       ` Dr. David Alan Gilbert
2025-09-10 18:03 ` [PATCH v3 18/20] util: add support for formatting a program " Daniel P. Berrangé
2025-09-11 18:07   ` Richard Henderson
2025-09-11 18:08     ` Richard Henderson
2025-09-12 16:33     ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 19/20] util: add support for formatting thread info " Daniel P. Berrangé
2025-09-11 18:11   ` Richard Henderson
2025-09-12  8:36     ` Daniel P. Berrangé
2025-09-10 18:03 ` [PATCH v3 20/20] util: add brackets around guest name in message context Daniel P. Berrangé
2025-09-11 18:12   ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).