Re: [PATCH V12 13/15] monitor/hmp: display IOThread holders
Zhang Chen <[email protected]>
| Newsgroups | org.nongnu.qemu-devel |
|---|---|
| Message-ID | <CAK3tnvL0N3AK78zwZVLP7ycujGeEHhmyuM6VG+LQd3GRg5CtbA@mail.gmail.com> |
On Thu, Aug 20, 2026 at 4:17 PM Markus Armbruster <[email protected]> wrote: > > Zhang Chen <[email protected]> writes: > > > Display holder information in info iothreads to aid manual debugging. > > Omit the holders line when an IOThread has no holders. > > > > Signed-off-by: Zhang Chen <[email protected]> > > --- > > monitor/hmp-cmds.c | 21 +++++++++++++++++++++ > > 1 file changed, 21 insertions(+) > > > > diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c > > index e9fb8d827a..41a813e79f 100644 > > --- a/monitor/hmp-cmds.c > > +++ b/monitor/hmp-cmds.c > > @@ -240,11 +240,32 @@ void hmp_info_iothreads(Monitor *mon, const QDict *qdict) > > IOThreadInfoList *info_list = qmp_query_iothreads(NULL); > > IOThreadInfoList *info; > > IOThreadInfo *value; > > + IOThreadHolderList *h; > > > > for (info = info_list; info; info = info->next) { > > value = info->value; > > monitor_printf(mon, "%s:\n", value->id); > > monitor_printf(mon, " thread_id=%" PRId64 "\n", value->thread_id); > > + monitor_printf(mon, " holders="); > > + for (h = value->holders; h; h = h->next) { > > + IOThreadHolder *holder = h->value; > > + > > + switch (holder->type) { > > + case IO_THREAD_HOLDER_KIND_BLOCK_EXPORT: > > + monitor_printf(mon, "[block-export: %s]", > > + holder->u.block_export.export_id); > > + break; > > + case IO_THREAD_HOLDER_KIND_QOM_OBJECT: > > + monitor_printf(mon, "[qom-path: %s]", > > + holder->u.qom_object.qom_path); > > + break; > > + default: > > + monitor_printf(mon, "[unknown]"); > > + break; > > This is unreachable. Please use > > default: > g_assert_not_reached(); > > to make it obvious. > > > + } > > + } > > + monitor_printf(mon, "\n"); > > + > > monitor_printf(mon, " poll-max-ns=%" PRId64 "\n", value->poll_max_ns); > > monitor_printf(mon, " poll-grow=%" PRId64 "\n", value->poll_grow); > > monitor_printf(mon, " poll-shrink=%" PRId64 "\n", value->poll_shrink); > > Quick test: > > $ qemu-system-x86_64 -S -nodefaults -display none -chardev socket,id=chr-qmp,path=test-qmp,server=on,wait=off -object monitor-qmp,id=qmp,chardev=chr-qmp -monitor stdio > QEMU 11.1.50 monitor - type 'help' for more information > (qemu) info iothreads > (qemu) q > > Hmm, no output? The QMP monitor should be holding the monitor I/O > thread. To confirm that, I made monitor_complete() print things (patch > appended), and got > > ### monitor qmp holding iothread mon_iothread > ### monitor compat_monitor0 without iothread > > What's going on here? > This is expected with the existing query-iothreads behavior. mon_iothread is created under the internal object root, while qmp_query_iothreads() only walks /objects, so internal IOThreads are intentionally not exposed through QMP/HMP. I prefer to preserve that behavior in this series, since exposing internal IOThreads would require additional API decisions, including handling ID collisions with user-created IOThreads. I’ll also change the unreachable default case to g_assert_not_reached(). Thanks Chen > > diff --git a/monitor/monitor.c b/monitor/monitor.c > index 26e7ef4d35..57672dbe0e 100644 > --- a/monitor/monitor.c > +++ b/monitor/monitor.c > @@ -751,8 +751,13 @@ static void monitor_complete(UserCreatable *uc, Error **errp) > }; > > mon->ctx = iothread_ref_and_get_aio_context(mon_iothread, &io_holder); > + printf("### monitor %s holding iothread %s\n", > + object_get_canonical_path_component(OBJECT(mon)), > + iothread_get_id(mon_iothread)); > } else { > mon->ctx = qemu_get_aio_context(); > + printf("### monitor %s without iothread\n", > + object_get_canonical_path_component(OBJECT(mon))); > } > mon->accept_input_bh = aio_bh_new(mon->ctx, monitor_accept_input, mon); > } >