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);
>  }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.