qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
	qemu-devel@nongnu.org, "Michael Roth" <mdroth@linux.vnet.ibm.com>,
	"Luiz Capitulino" <lcapitulino@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Andreas Färber" <afaerber@suse.de>
Subject: Re: [Qemu-devel] [RFC PATCH] qapi: split visit_end_struct() into pieces
Date: Wed, 7 Oct 2015 08:57:31 -0600	[thread overview]
Message-ID: <561532DB.1010301@redhat.com> (raw)
In-Reply-To: <877fmydh22.fsf@blackfin.pond.sub.org>

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

On 10/07/2015 06:00 AM, Markus Armbruster wrote:

>>> Looks like we're getting drawn into visitor contract territory again.
>>>

>> +++ b/hmp.c
>> @@ -1658,8 +1658,9 @@ void hmp_object_add(Monitor *mon, const QDict *qdict)
>>
>>      object_add(type, id, pdict, opts_get_visitor(ov), &err);
>>
>> +    visit_check_struct(opts_get_visitor(ov), &err_end);
>>  out_end:
>> -    visit_end_struct(opts_get_visitor(ov), &err_end);
>> +    visit_end_struct(opts_get_visitor(ov));
>>      if (!err && err_end) {
>>          qmp_object_del(id, NULL);
>>      }
> 
> Preexisting: calling object_add() before visit_end_struct() is awkward.
> Can we simplify things now we have separate visit_check_struct() and
> visit_end_struct()?  Call visit_check_struct() before object_add(),
> bypass object_add() on error, avoiding the need to undo it with
> qmp_object_del().

Okay, it sounds like I'm sitting on a pile of pre-patch cleanups, and
that I'm on the right track for having done the split.


>> +++ b/include/qapi/visitor.h
>> @@ -56,11 +56,19 @@ typedef struct GenericList
>>  void visit_start_struct(Visitor *v, void **obj, const char *kind,
>>                          const char *name, size_t size, Error **errp);
>>  /**
>> + * Check whether completing a struct is safe.
> 
> "Safe"?  We need to complete the struct visit with visit_end_struct()
> regardless of what this function returns...
> 
>> + * Should be called prior to visit_end_struct() if all other intermediate
>> + * visit steps were successful, to allow the caller one last chance to
>> + * report errors such as remaining data that was not consumed by the visit.
>> + */
>> +void visit_check_struct(Visitor *v, Error **errp);

Maybe:

Declare the current struct complete, and check for unvisited contents.

>>  static void
>> -opts_end_struct(Visitor *v, Error **errp)
>> +opts_check_struct(Visitor *v, Error **errp)
>>  {
>>      OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
>>      GQueue *any;
> 
>        if (--ov->depth > 0) {
> 
> Do we want to decrement ov->depth here?  We'll decrement it again in
> opts_end_struct()...

Oh, good catch.  This was an awkward split, and I got it off-by-one.

>> +++ b/qapi/qmp-input-visitor.c
>> @@ -88,14 +88,14 @@ static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
>>      qiv->nb_stack++;
>>  }
>>
>> -/** Only for qmp_input_pop. */
>> +/** Only for qmp_input_check. */
> 
> Drop the comment instead?
> 
> Aside: a loop would be more idiomatic C.  Leave higher order functions
> to languages that are actually equipped for the job.
> 
>>  static gboolean always_true(gpointer key, gpointer val, gpointer user_pkey)
>>  {
>>      *(const char **)user_pkey = (const char *)key;
>>      return TRUE;
>>  }
>>
>> -static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
>> +static void qmp_input_check(QmpInputVisitor *qiv, Error **errp)
>>  {
>>      assert(qiv->nb_stack > 0);
>>
>> @@ -107,6 +107,17 @@ static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
>>                  g_hash_table_find(top_ht, always_true, &key);

always_true() exists for g_hash_table_find() - unless you know of some
other way to grab any arbitrary element of the hash table that doesn't
require a higher-order function.


>> +++ b/scripts/qapi-event.py
>> @@ -73,13 +73,14 @@ def gen_event_send(name, arg_type):
>>          ret += gen_err_check()
>>          ret += gen_visit_fields(arg_type.members, need_cast=True)
>>          ret += mcgen('''
>> -    visit_end_struct(v, &err);
>> +    visit_check_struct(v, &err);
>>      if (err) {
>>          goto out;
>>      }
>> +    visit_end_struct(v);
>>
>>      obj = qmp_output_get_qobject(qov);
>> -    g_assert(obj != NULL);
>> +    g_assert(obj);
> 
> I prefer the more laconic form myself, but it's an unrelated change.

I can split that one-line change into a more appropriate patch.

>>  out_obj:
>>      error_propagate(errp, err);
>>      err = NULL;
>>      visit_end_union(v, !!(*obj)->data, &err);
> 
> Should visit_end_union() be similarly split?  Or should its Error **
> parameter be dropped?  As far as I can tell, no visitor implements this
> method...
> 

visit_end_union() gets completely dropped in a different patch.  See v5
28/46.


>> +++ b/tests/test-qmp-output-visitor.c
>> @@ -194,10 +194,11 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
>>      }
>>      visit_type_str(v, &(*obj)->string, "string", &err);
>>
>> +    if (!err) {
>> +        visit_check_struct(v, &err);
>> +    }
> 
> ... but here, you guard it with an if.  Either way works, but I'd like
> us to pick just one for the generators.

Sure.


>> -    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
>> +    for (*head = i = visit_next_list(v, head, &err);
>> +         !err && i;
>> +         i = visit_next_list(v, &i, &err)) {
>>          TestStructList *native_i = (TestStructList *)i;
>> -        visit_type_TestStruct(v, &native_i->value, NULL, errp);
>> +        visit_type_TestStruct(v, &native_i->value, NULL, &err);
>>      }
> 
> Is this a silent bug fix?  Before your patch, the loop doesn't break on
> error.
> 

Yes, looks like it. And all the more reason for our test code to NOT
hand-write this, but to rely on the generator (so that we are testing a
single version of visit_* calls, rather than subtle differences in
generated vs. hand-rolled).


>> +++ b/vl.c
>> @@ -2796,23 +2796,25 @@ static int object_create(void *opaque, QemuOpts *opts, Error **errp)
>>      qdict_del(pdict, "qom-type");
>>      visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
>>      if (err) {
>> -        goto out;
>> +        goto obj_out;

>> +obj_out:
>> +    visit_end_struct(opts_get_visitor(ov));
>>      if (err) {
>>          qmp_object_del(id, NULL);
>>      }
> 
> Silent bug fix: we now call visit_end_struct() even on error.  Impact?
> Separate patch?

Yes, separate patch, and I'll evaluate impact there.

So sounds like I should proceed with this RFC (which means more respin
of my other patches, before I can post subset C - but that's okay, since
we aren't even through reviewing subset B, nor is subset A in a pull
request).

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

  parent reply	other threads:[~2015-10-07 14:57 UTC|newest]

Thread overview: 108+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-21 21:57 [Qemu-devel] [PATCH v5 00/46] post-introspection cleanups, and qapi-ify netdev_add Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 01/46] qapi: Sort qapi-schema tests Eric Blake
2015-09-23 14:26   ` Eric Blake
2015-09-23 15:09     ` Markus Armbruster
2015-09-23 15:19       ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 02/46] qapi: Clean up qapi.py per pep8 Eric Blake
2015-09-22 14:00   ` Markus Armbruster
2015-09-22 14:58     ` Eric Blake
2015-09-23  9:20       ` Markus Armbruster
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 03/46] qapi: Test for C member name collisions Eric Blake
2015-09-22 15:23   ` Markus Armbruster
2015-09-22 17:52     ` Eric Blake
2015-09-23  9:43       ` Markus Armbruster
2015-09-23 12:45         ` Eric Blake
2015-09-23 14:02           ` Markus Armbruster
2015-09-23 14:19             ` Eric Blake
2015-09-23 15:12               ` Markus Armbruster
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 04/46] qapi: Add tests for empty unions Eric Blake
2015-09-24 14:16   ` Markus Armbruster
2015-09-24 15:52     ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 05/46] qapi: Test use of 'number' within alternates Eric Blake
2015-09-24 14:36   ` Markus Armbruster
2015-09-24 16:00     ` Eric Blake
2015-09-24 16:29       ` Markus Armbruster
2015-09-25 22:32         ` Eric Blake
2015-09-28  9:26           ` Markus Armbruster
2015-09-25 22:50         ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 06/46] qapi: Improve 'include' error message Eric Blake
2015-09-24 14:39   ` Markus Armbruster
2015-09-24 16:04     ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 07/46] qapi: Don't pass pre-existing error to later call Eric Blake
2015-09-24 14:58   ` Markus Armbruster
2015-09-24 16:14     ` Eric Blake
2015-09-26 21:05       ` Eric Blake
2015-09-28  9:14         ` Markus Armbruster
2015-10-06 21:10           ` [Qemu-devel] [RFC PATCH] qapi: split visit_end_struct() into pieces Eric Blake
2015-10-07 12:00             ` Markus Armbruster
2015-10-07 13:08               ` Markus Armbruster
2015-10-07 14:57               ` Eric Blake [this message]
2015-10-07 15:23                 ` Markus Armbruster
2015-09-26 21:41     ` [Qemu-devel] [PATCH v5 07/46] qapi: Don't pass pre-existing error to later call Eric Blake
2015-09-27  2:26       ` Eric Blake
2015-09-28  9:24       ` Markus Armbruster
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 08/46] qapi: Reuse code for flat union base validation Eric Blake
2015-09-25 16:30   ` Markus Armbruster
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 09/46] qapi: Use consistent generated code patterns Eric Blake
2015-09-25 16:54   ` Markus Armbruster
2015-09-25 19:06     ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 10/46] qapi: Merge generation of per-member visits Eric Blake
2015-09-28  6:17   ` Markus Armbruster
2015-09-28 15:40     ` Eric Blake
2015-09-29  7:37       ` Markus Armbruster
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 11/46] qapi: Don't use info as witness of implicit object type Eric Blake
2015-09-28 12:43   ` Markus Armbruster
2015-09-29  3:58     ` Eric Blake
2015-09-29  7:51       ` Markus Armbruster
2015-09-30  4:13         ` [Qemu-devel] [RFC PATCH] qapi: Use callback to determine visit filtering Eric Blake
2015-10-01  6:12           ` Markus Armbruster
2015-10-01 14:09             ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 12/46] qapi: Track location that created an implicit type Eric Blake
2015-09-28 12:56   ` Markus Armbruster
2015-09-29  4:03     ` Eric Blake
2015-09-29  8:02       ` Markus Armbruster
2015-09-30 16:02         ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 13/46] qapi: Track owner of each object member Eric Blake
2015-09-30 16:06   ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 14/46] qapi: Detect collisions in C member names Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 15/46] qapi: Defer duplicate member checks to schema check() Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 16/46] qapi: Detect base class loops Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 17/46] qapi: Provide nicer array names in introspection Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 18/46] qapi-introspect: Guarantee particular sorting Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 19/46] qapi: Simplify visiting of alternate types Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 20/46] qapi: Fix alternates that accept 'number' but not 'int' Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 21/46] qmp: Fix reference-counting of qnull on empty output visit Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 22/46] qapi: Don't abuse stack to track qmp-output root Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 23/46] qapi: Remove dead visitor code Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 24/46] qapi: Document visitor interfaces Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 25/46] qapi: Plug leaks in test-qmp-input-visitor Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 26/46] qapi: Test failure in middle of array parse Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 27/46] qapi: Simplify visits of optional fields Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 28/46] qapi: Rework deallocation of partial struct Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 29/46] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 30/46] net: use Netdev instead of NetClientOptions in client init Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 31/46] qapi: use 'type' in generated C code to match QMP union wire form Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 32/46] qapi: Hide tag_name data member of variants Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 33/46] vnc: hoist allocation of VncBasicInfo to callers Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 34/46] qapi: Unbox base members Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 35/46] qapi-visit: Remove redundant functions for flat union base Eric Blake
2015-09-23 20:55   ` Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 36/46] qapi: Avoid use of 'data' member of qapi unions Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 37/46] qapi: Forbid empty unions and useless alternates Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 38/46] qapi: Drop useless 'data' member of unions Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 39/46] qapi: Plumb in 'box' to qapi generator lower levels Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 40/46] qapi: Implement boxed structs for commands/events Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 41/46] qapi: Support boxed unions Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 42/46] qapi: support implicit structs in OptsVisitor Eric Blake
2015-09-21 21:57 ` [Qemu-devel] [PATCH v5 43/46] qapi: Change Netdev into a flat union Eric Blake
2015-09-21 21:58 ` [Qemu-devel] [PATCH v5 44/46] net: Use correct type for bool flag Eric Blake
2015-09-21 21:58 ` [Qemu-devel] [PATCH v5 45/46] net: Complete qapi-fication of netdev_add Eric Blake
2015-09-23 15:40   ` Paolo Bonzini
2015-09-23 16:37     ` Eric Blake
2015-09-25 16:48       ` Paolo Bonzini
2015-09-28  9:31         ` Markus Armbruster
2015-09-28 11:29           ` Paolo Bonzini
2015-09-21 21:58 ` [Qemu-devel] [PATCH v5 46/46] qapi: Allow anonymous base for flat union Eric Blake
2015-09-23 20:59   ` Eric Blake
2015-09-28 13:07 ` [Qemu-devel] [PATCH v5 00/46] post-introspection cleanups, and qapi-ify netdev_add Markus Armbruster
2015-09-29  3:43   ` Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=561532DB.1010301@redhat.com \
    --to=eblake@redhat.com \
    --cc=afaerber@suse.de \
    --cc=armbru@redhat.com \
    --cc=lcapitulino@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).