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 --]
next prev 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).