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

> On Fri, Sep 19, 2025 at 02:43:41PM +0200, Markus Armbruster wrote:
>> Daniel P. Berrangé <berra...@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é <berra...@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


Reply via email to