[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [Qemu-devel] [PATCH] RFC: chardev: mark the calls that allow an implicit mux monitor



Hi
On Mon, Aug 27, 2018 at 10:10 AM Markus Armbruster <armbru@xxxxxxxxxx> wrote:
>
> Marc-André Lureau <marcandre.lureau@xxxxxxxxx> writes:
>
> > Hi
> > On Fri, Aug 24, 2018 at 9:37 AM Markus Armbruster <armbru@xxxxxxxxxx> wrote:
> >>
> >> Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> writes:
> >>
> >> > This is mostly for readability of the code. Let's make it clear which
> >> > callers can create an implicit monitor when the chardev is muxed.
> >> >
> >> > This will also enforce a safer behaviour, as we don't really support
> >> > creating monitor anywhere/anytime at the moment.
> >> >
> >> > There are documented cases, such as: -serial/-parallel/-virtioconsole
> >> > and to less extent -debugcon.
> >> >
> >> > Less obvious and questionnable ones are -gdb and Xen console. Add a
> >> > FIXME note for those, but keep the support for now.
> >> >
> >> > Other qemu_chr_new() callers either have a fixed parameter/filename
> >> > string, or do preliminary checks on the string (such as slirp), or do
> >> > not need it, such as -qtest.
> >> >
> >> > On a related note, the list of monitor creation places:
> >> >
> >> > - the chardev creators listed above: all from command line (except
> >> >   perhaps Xen console?)
> >> >
> >> > - -gdb & hmp gdbserver will create a "GDB monitor command" chardev
> >> >   that is wired to an HMP monitor.
> >> >
> >> > - -mon command line option
> >>
> >> Aside: the question "what does it mean to connect a monitor to a chardev
> >> that has an implicit monitor" crosses my mind.  Next thought is "the
> >> day's too short to go there".
> >>
> >> > From this short study, I would like to think that a monitor may only
> >> > be created in the main thread today, though I remain skeptical :)
> >>
> >> Hah!
> >>
> >> > Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx>
> >> > ---
> >> >  include/chardev/char.h | 18 +++++++++++++++++-
> >> >  chardev/char.c         | 21 +++++++++++++++++----
> >> >  gdbstub.c              |  6 +++++-
> >> >  hw/char/xen_console.c  |  5 ++++-
> >> >  vl.c                   |  8 ++++----
> >> >  5 files changed, 47 insertions(+), 11 deletions(-)
> >> >
> >> > diff --git a/include/chardev/char.h b/include/chardev/char.h
> >> > index 6f0576e214..be2b9b817e 100644
> >> > --- a/
> >> > +++ b/include/chardev/char.h
> >> > @@ -105,6 +105,7 @@ ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts,
> >> >   * @qemu_chr_new:
> >> >   *
> >> >   * Create a new character backend from a URI.
> >> > + * Do not implicitely initialize a monitor if the chardev is muxed.
> >> >   *
> >> >   * @label the name of the backend
> >> >   * @filename the URI
> >> > @@ -113,6 +114,19 @@ ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts,
> >> >   */
> >> >  Chardev *qemu_chr_new(const char *label, const char *filename);
> >> >
> >> > +/**
> >> > + * @qemu_chr_new_mux_mon:
> >> > + *
> >> > + * Create a new character backend from a URI.
> >> > + * Implicitely initialize a monitor if the chardev is muxed.
> >> > + *
> >> > + * @label the name of the backend
> >> > + * @filename the URI
> >>
> >> I'm no friend of GTK-Doc style, but where we use it, we should use it
> >> correctly: put a colon after @param.
> >
> > I copied existing comment... Should I fixed all others in the headers?
>
> Do we expect to actually *use* doc comments for anything?  We haven't in
> a decade or so, but if we still expect to all the same, then not fixing
> them up now merely delays the inevitable.
>
> Do we think adding the colons makes the comments easier to read?  For
> what it's worth, I do.
>
> Decision's up to you.

Let's improve it.

>
> >> > + *
> >> > + * Returns: a new character backend
> >> > + */
> >> > +Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename);
> >> > +
> >> >  /**
> >> >   * @qemu_chr_change:
> >> >   *
> >> > @@ -138,10 +152,12 @@ void qemu_chr_cleanup(void);
> >> >   *
> >> >   * @label the name of the backend
> >> >   * @filename the URI
> >> > + * @with_mux_mon if chardev is muxed, initialize a monitor
> >> >   *
> >> >   * Returns: a new character backend
> >> >   */
> >> > -Chardev *qemu_chr_new_noreplay(const char *label, const char *filename);
> >> > +Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
> >> > +                               bool with_mux_mon);
> >> >
> >> >  /**
> >> >   * @qemu_chr_be_can_write:
> >> > diff --git a/chardev/char.c b/chardev/char.c
> >> > index 76d866e6fe..2c295ad676 100644
> >> > --- a/chardev/char.c
> >> > +++ b/chardev/char.c
> >> > @@ -683,7 +683,8 @@ out:
> >> >      return chr;
> >> >  }
> >> >
> >> > -Chardev *qemu_chr_new_noreplay(const char *label, const char *filename)
> >> > +Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
> >> > +                               bool with_mux_mon)
> >> >  {
> >> >      const char *p;
> >> >      Chardev *chr;
> >> > @@ -702,17 +703,19 @@ Chardev *qemu_chr_new_noreplay(const char *label, 
> >> > const char *filename)
> >> >      if (err) {
> >> >          error_report_err(err);
> >> >      }
> >> > -    if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
> >> > +    if (with_mux_mon && chr && qemu_opt_get_bool(opts, "mux", 0)) {
> >> >          monitor_init(chr, MONITOR_USE_READLINE);
> >> >      }
> >>
> >> When !chr, the function already failed, so that part of the condition is
> >> uninteresting here[*].
> >
> > yeah, hopefully err is always set if the return value is NULL.
> >
> >> That leaves qemu_opt_get_bool(opts, "mux", 0).  Behavior changes when
> >> it's true and with_mux_mon is false: we no longer create a monitor.
> >>
> >> Can this happen?
> >>
> >> If it can, when exactly, and how does it affect externally visible
> >> behavior?
> >
> > we could add an assert() for with_mux_mon || !opt("mux").
>
> Hmm.  See my analysis below.
>
> >> I guess we'll see below.
> >>
> >> >      qemu_opts_del(opts);
> >> >      return chr;
> >> >  }
> >> >
> >> > -Chardev *qemu_chr_new(const char *label, const char *filename)
> >> > +static Chardev *qemu_chr_new_with_mux_mon(const char *label,
> >> > +                                          const char *filename,
> >> > +                                          bool with_mux_mon)
> >> >  {
> >> >      Chardev *chr;
> >> > -    chr = qemu_chr_new_noreplay(label, filename);
> >> > +    chr = qemu_chr_new_noreplay(label, filename, with_mux_mon);
> >> >      if (chr) {
> >> >          if (replay_mode != REPLAY_MODE_NONE) {
> >> >              qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_REPLAY);
> >> > @@ -726,6 +729,16 @@ Chardev *qemu_chr_new(const char *label, const char 
> >> > *filename)
> >> >      return chr;
> >> >  }
> >> >
> >> > +Chardev *qemu_chr_new(const char *label, const char *filename)
> >> > +{
> >> > +    return qemu_chr_new_with_mux_mon(label, filename, false);
> >> > +}
> >> > +
> >> > +Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename)
> >> > +{
> >> > +    return qemu_chr_new_with_mux_mon(label, filename, true);
> >> > +}
> >> > +
> >> >  static int qmp_query_chardev_foreach(Object *obj, void *data)
> >> >  {
> >> >      Chardev *chr = CHARDEV(obj);
> >>
> >> Note for later: qemu_chr_new() changes behavior.  To avoid that, call
> >> qemu_chr_new_mux_mon() instead.
> >>
> >> > diff --git a/gdbstub.c b/gdbstub.c
> >> > index d6ab95006c..963531ea90 100644
> >> > --- a/gdbstub.c
> >> > +++ b/gdbstub.c
> >> > @@ -2038,7 +2038,11 @@ int gdbserver_start(const char *device)
> >> >              sigaction(SIGINT, &act, NULL);
> >> >          }
> >> >  #endif
> >> > -        chr = qemu_chr_new_noreplay("gdb", device);
> >> > +        /*
> >> > +         * FIXME: it's a bit weird to allow using a mux chardev here
> >> > +         * and setup implicitely a monitor. We may want to break this.
> >> > +         */
> >> > +        chr = qemu_chr_new_noreplay("gdb", device, true);
> >> >          if (!chr)
> >> >              return -1;
> >> >      }
> >>
> >> No behavioral change.  The patch does exactly what the commit message
> >> claims, namely mark potential implicit monitor creation in the source
> >> code.
> >>
> >> > diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
> >> > index 8b4b4bf523..6a231d487b 100644
> >> > --- a/hw/char/xen_console.c
> >> > +++ b/hw/char/xen_console.c
> >> > @@ -207,7 +207,10 @@ static int con_init(struct XenDevice *xendev)
> >> >      } else {
> >> >          snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
> >> >          qemu_chr_fe_init(&con->chr,
> >> > -                         qemu_chr_new(label, output), &error_abort);
> >> > +                         /*
> >> > +                          * FIXME: should it support implicit muxed 
> >> > monitors?
> >> > +                          */
> >> > +                         qemu_chr_new_mux_mon(label, output), 
> >> > &error_abort);
> >> >      }
> >>
> >> Likewise, with a terser comment.
> >>
> >> >
> >> >      xenstore_store_pv_console_info(con->xendev.dev,
> >> > diff --git a/vl.c b/vl.c
> >> > index 16b913f9d5..20b5f321ec 100644
> >> > --- a/vl.c
> >> > +++ b/vl.c
> >> > @@ -2425,7 +2425,7 @@ static int serial_parse(const char *devname)
> >> >      snprintf(label, sizeof(label), "serial%d", index);
> >> >      serial_hds = g_renew(Chardev *, serial_hds, index + 1);
> >> >
> >> > -    serial_hds[index] = qemu_chr_new(label, devname);
> >> > +    serial_hds[index] = qemu_chr_new_mux_mon(label, devname);
> >> >      if (!serial_hds[index]) {
> >> >          error_report("could not connect serial device"
> >> >                       " to character backend '%s'", devname);
> >>
> >> Likewise, without a comment, because implicit monitor is a feature
> >> here.  Correct?
> >
> > right
> >
> >>
> >> > @@ -2461,7 +2461,7 @@ static int parallel_parse(const char *devname)
> >> >          exit(1);
> >> >      }
> >> >      snprintf(label, sizeof(label), "parallel%d", index);
> >> > -    parallel_hds[index] = qemu_chr_new(label, devname);
> >> > +    parallel_hds[index] = qemu_chr_new_mux_mon(label, devname);
> >> >      if (!parallel_hds[index]) {
> >> >          error_report("could not connect parallel device"
> >> >                       " to character backend '%s'", devname);
> >>
> >> Likewise.
> >>
> >> > @@ -2492,7 +2492,7 @@ static int virtcon_parse(const char *devname)
> >> >      qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort);
> >> >
> >> >      snprintf(label, sizeof(label), "virtcon%d", index);
> >> > -    virtcon_hds[index] = qemu_chr_new(label, devname);
> >> > +    virtcon_hds[index] = qemu_chr_new_mux_mon(label, devname);
> >> >      if (!virtcon_hds[index]) {
> >> >          error_report("could not connect virtio console"
> >> >                       " to character backend '%s'", devname);
> >>
> >> Likewise.
> >>
> >> > @@ -2508,7 +2508,7 @@ static int debugcon_parse(const char *devname)
> >> >  {
> >> >      QemuOpts *opts;
> >> >
> >> > -    if (!qemu_chr_new("debugcon", devname)) {
> >> > +    if (!qemu_chr_new_mux_mon("debugcon", devname)) {
> >> >          exit(1);
> >> >      }
> >> >      opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, 
> >> > NULL);
> >>
> >> Likewise.
> >>
> >> Not visible in the patch: calls of qemu_chr_new() not changed to
> >> qemu_chr_new_mux_mon().  These are:
> >>
> >> * qtest.c: qtest_init()
>
> Calls qemu_chr_new("qtest", qtest_chrdev), where @qtest_chrdev is the
> argument of CLI option -qtest.
>
> I figure -qtest mon:... makes no sense.  But failing an assertion then
> isn't nice.  We need to reject nonsense with a suitable error message.
>
> Perhaps the easiest way to do so would be passing @with_mux_mon to
> qemu_chr_parse_compat(), and reject mon: there unless with_mux_mon.

Done

>
> >> * net/slirp.c: slirp_guestfwd()
>
> Calls qemu_chr_new(buf, p), where @p points into some config string that
> I guess comes from the user, too.  If that's true, same story as for
> qtest_init().

Actually, I got that one wrong, you can use mon: here.. Let's keep it
for now, add a FIXME.

>
> >> * hw/char/xen_console.c: con_init()
>
> Calls qemu_chr_new(label, output), where @output comes from xenstore.
> Same story again.
>
> >> * Several more in hw/, all with literal @filename argument that doesn't
> >>   enable mux.
>
> The assertion can't fire.
>
> Aside: would be nice to bypass parsing (and the possibility of error
> that comes with it) here, but it's probably not worth the trouble to
> change.

Yeah, some othre day :)

> >> * tests/test-char.c
> >>
> >> * tests/vhost-user-test.c
> >>
> >> I figure these are meant to be covered by commit message paragraph
> >>
> >>     Other qemu_chr_new() callers either have a fixed parameter/filename
> >>     string, or do preliminary checks on the string (such as slirp), or do
> >>     not need it, such as -qtest.
> >>
> >> A non-RFC patch should add enough detail to let the reviewer understand
> >> each case without having to dig through the code himself.  Since I
> >> didn't do that, I can't give my R-by.  I can say I like the idea.
> >
> > ok, I'll update the patch & commit message.
> >
> >>
> >>
> >> [*] Aside: I prefer cleanly separated error paths, like this:
> >>
> >> Chardev *qemu_chr_new_noreplay(const char *label, const char *filename)
> >> {
> >>     const char *p;
> >>     Chardev *chr;
> >>     QemuOpts *opts;
> >>     Error *err = NULL;
> >>     bool mux;
> >>
> >>     if (strstart(filename, "chardev:", &p)) {
> >>         return qemu_chr_find(p);
> >>     }
> >>
> >>     opts = qemu_chr_parse_compat(label, filename);
> >>     if (!opts)
> >>         return NULL;
> >>
> >>     mux = qemu_opt_get_bool(opts, "mux", 0);
> >>     chr = qemu_chr_new_from_opts(opts, &err);
> >>     qemu_opts_del(opts);
> >>     if (!chr) {
> >>         error_report_err(err);
> >>         return NULL;
> >>     }
> >>     if (mux) {
> >>         monitor_init(chr, MONITOR_USE_READLINE);
> >>     }
> >>     return chr;
> >> }
> >>
> >
> > thanks



-- 
Marc-André Lureau

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.