From: Eric Blake <eblake@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-devel@nongnu.org, Michael Roth <mdroth@linux.vnet.ibm.com>
Subject: Re: [Qemu-devel] [PATCH v14 19/19] qapi: Change visit_type_FOO() to no longer return partial objects
Date: Wed, 27 Apr 2016 15:51:39 -0600 [thread overview]
Message-ID: <5721346B.4080000@redhat.com> (raw)
In-Reply-To: <87lh4forjm.fsf@dusky.pond.sub.org>
[-- Attachment #1: Type: text/plain, Size: 5816 bytes --]
On 04/15/2016 08:49 AM, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
>
>> Returning a partial object on error is an invitation for a careless
>> caller to leak memory. As no one outside the testsuite was actually
>> relying on these semantics, it is cleaner to just document and
>> guarantee that ALL pointer-based visit_type_FOO() functions always
>> leave a safe value in *obj during an input visitor (either the new
>> object on success, or NULL if an error is encountered), so callers
>> can now unconditionally use qapi_free_FOO() to clean up regardless
>> of whether an error occurred.
>
> Hmm, wasn't the "assign null on error" part done in a prior patch?
> Checking... no, only half of it, in PATCH 03: there, we went from "may
> store an incomplete object on error" to "store either an incomplete
> object or null on error". Now we go on to just "store null on error".
> Correct?
Yes. I'll tweak the wording to make it clearer.
>
>> The decision is done by enhancing qapi-visit-core to return true
>> for input visitors (the callbacks themselves do not need
>> modification); since we've documented that visit_end_* must be
>> called after any successful visit_start_*, that is a sufficient
>> point for knowing that something was allocated during start.
>
> I find this sentence a bit confusing. Let me try:
>
> To help visitor-agnostic code, such as the generated qapi-visit.c,
> make the visit_end_FOO() return true when something was allocated.
> Easily done in the visitor core, no need to change the callbacks.
>
> But see my comments on the visit_end_FOO() inline.
Reply below, where your comments are indeed worth thinking about.
>
>> Note that we still leave *obj unchanged after a scalar-based
>> visit_type_FOO(); I did not feel like auditing all uses of
>> visit_type_Enum() to see if the callers would tolerate a specific
>> sentinel value (not to mention having to decide whether it would
>> be better to use 0 or ENUM__MAX as that sentinel).
>
> Should this note be in PATCH 03?
>
> The inconsistency isn't pretty, but tolerable if it simplifies things.
No. Patch 03 fixed visit_start_struct, not visit_type_FOO. Since it is
this patch that is tweaking visit_type_FOO, I have to explain why
visit_type_ENUM preserves values, while visit_type_OBJ sets to NULL.
>> *
>> - * FIXME: At present, input visitors may allocate an incomplete *@obj
>> - * even when visit_type_FOO() reports an error. Using an output
>> - * visitor with an incomplete object has undefined behavior; callers
>> - * must call qapi_free_FOO() (which uses the dealloc visitor, and
>> - * safely handles an incomplete object) to avoid a memory leak.
>> + * If an error is detected during visit_type_FOO() with an input
>> + * visitor, then *@obj will be NULL for pointer types, and left
>> + * unchanged for scalar types.
>
> Okay.
And this matches the commit message explaining the difference between
scalar and object (and also applies to visit_type_int being a scalar
that leaves the value unchanged on error).
>
>> + * Using an output visitor with an
>> + * incomplete object has undefined behavior (other than a special case
>> + * for visit_type_str() treating NULL like ""), while the dealloc
>> + * visitor safely handles incomplete objects.
>
> Where do the incomplete objects come from now? I thought this patch
> gets rid of them.
Still possible to create one by manual means, just no longer possible
from a QAPI input visitor. I'll tweak the wording.
>> -void visit_end_struct(Visitor *v);
>> +bool visit_end_struct(Visitor *v);
>
> I generally like functions to return something useful, but not in this
> case, because the function name gives you no clue about its value.
> Consider:
>
> if (visit_end_struct(v) && err) {
> qapi_free_FOO(*obj);
> *obj = NULL;
> }
>
> To find out what this means, a reader not familiar with visitors almost
> certainly needs to refer to visit_end_struct()'s contract or code.
>
> Compare:
>
> visit_end_struct(v);
> if (err && v->type == VISITOR_INPUT) {
v->type is a layering violation...
> qapi_free_FOO(*obj);
> *obj = NULL;
> }
>
> Or:
>
> visit_end_struct(v);
> if (err && visit_is_input(v)) {
...but this is doable by exporting visit_is_input().
> qapi_free_FOO(*obj);
> *obj = NULL;
> }
Makes the generated code have more lines, but who really cares. So
consider it done in v15.
>> +++ b/qapi/qapi-visit-core.c
>> @@ -23,11 +23,17 @@
>> void visit_start_struct(Visitor *v, const char *name, void **obj,
>> size_t size, Error **errp)
>> {
>> + Error *err = NULL;
>> +
>> if (obj) {
>> assert(size);
>> assert(v->type != VISITOR_OUTPUT || *obj);
>> }
>> - v->start_struct(v, name, obj, size, errp);
>> + v->start_struct(v, name, obj, size, &err);
>> + if (obj && v->type == VISITOR_INPUT) {
>> + assert(err || *obj);
>> + }
>> + error_propagate(errp, err);
>
> Sure this belongs to this patch? More of the same below.
Hmm. Patch 3 was the one that tightened semantics on visit_start, so I
can certainly try to hoist the added assertions there.
>> static void test_validate_fail_alternate(TestInputVisitorData *data,
>> const void *unused)
>> {
>> - UserDefAlternate *tmp = NULL;
>> + UserDefAlternate *tmp;
>
> Did this initialization become dead in PATCH 03 already?
Probably :)
--
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:[~2016-04-27 21:51 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-04-08 16:12 [Qemu-devel] [PATCH v14 00/19] qapi visitor cleanups (post-introspection cleanups subset E) Eric Blake
2016-04-08 16:12 ` [Qemu-devel] [PATCH v14 01/19] qapi: Consolidate object visitors Eric Blake
2016-04-13 12:48 ` Markus Armbruster
2016-04-13 16:13 ` Eric Blake
2016-04-15 15:05 ` Markus Armbruster
2016-04-08 16:12 ` [Qemu-devel] [PATCH v14 02/19] qapi-visit: Add visitor.type classification Eric Blake
2016-04-13 13:49 ` Markus Armbruster
2016-04-13 16:23 ` Eric Blake
2016-04-15 15:24 ` Markus Armbruster
2016-04-08 16:12 ` [Qemu-devel] [PATCH v14 03/19] qapi: Guarantee NULL obj on input visitor callback error Eric Blake
2016-04-13 14:04 ` Markus Armbruster
2016-04-08 16:12 ` [Qemu-devel] [PATCH v14 04/19] qmp: Drop dead command->type Eric Blake
2016-04-08 16:12 ` [Qemu-devel] [PATCH v14 05/19] qmp-input: Clean up stack handling Eric Blake
2016-04-13 15:53 ` Markus Armbruster
2016-04-13 16:36 ` Eric Blake
2016-04-13 16:40 ` Eric Blake
2016-04-15 15:27 ` Markus Armbruster
2016-04-08 16:12 ` [Qemu-devel] [PATCH v14 06/19] qmp-input: Don't consume input when checking has_member Eric Blake
2016-04-13 16:06 ` Markus Armbruster
2016-04-13 16:43 ` Eric Blake
2016-04-15 15:28 ` Markus Armbruster
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 07/19] qmp-input: Refactor when list is advanced Eric Blake
2016-04-13 17:38 ` Markus Armbruster
2016-04-13 19:58 ` Eric Blake
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 08/19] qapi: Document visitor interfaces, add assertions Eric Blake
2016-04-14 15:22 ` Markus Armbruster
2016-04-26 21:50 ` Eric Blake
2016-04-28 16:33 ` Markus Armbruster
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 09/19] tests: Add check-qnull Eric Blake
2016-04-14 16:13 ` Markus Armbruster
2016-04-14 17:37 ` Markus Armbruster
2016-04-14 18:54 ` Eric Blake
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 10/19] qapi: Add visit_type_null() visitor Eric Blake
2016-04-14 17:09 ` Markus Armbruster
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 11/19] qmp: Support explicit null during visits Eric Blake
2016-04-15 8:29 ` Markus Armbruster
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 12/19] spapr_drc: Expose 'null' in qom-get when there is no fdt Eric Blake
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 13/19] qmp: Tighten output visitor rules Eric Blake
2016-04-15 9:02 ` Markus Armbruster
2016-04-27 1:29 ` Eric Blake
2016-04-27 6:29 ` Markus Armbruster
2016-04-27 12:22 ` Eric Blake
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 14/19] qapi: Split visit_end_struct() into pieces Eric Blake
2016-04-15 11:03 ` Markus Armbruster
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 15/19] qapi-commands: Wrap argument visit in visit_start_struct Eric Blake
2016-04-15 11:42 ` Markus Armbruster
2016-04-26 12:56 ` Eric Blake
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 16/19] qom: Wrap prop " Eric Blake
2016-04-15 11:52 ` Markus Armbruster
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 17/19] qmp-input: Require struct push to visit members of top dict Eric Blake
2016-04-15 12:53 ` Markus Armbruster
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 18/19] qapi: Simplify semantics of visit_next_list() Eric Blake
2016-04-15 14:09 ` Markus Armbruster
2016-04-22 8:46 ` Markus Armbruster
2016-04-22 11:35 ` Markus Armbruster
2016-04-22 11:37 ` [Qemu-devel] [PATCH] tests/string-input-visitor: Add negative integer tests Markus Armbruster
2016-04-27 20:22 ` [Qemu-devel] [PATCH v14 18/19] qapi: Simplify semantics of visit_next_list() Eric Blake
2016-04-08 16:13 ` [Qemu-devel] [PATCH v14 19/19] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
2016-04-15 14:49 ` Markus Armbruster
2016-04-27 21:51 ` Eric Blake [this message]
2016-04-15 15:41 ` [Qemu-devel] [PATCH v14 00/19] qapi visitor cleanups (post-introspection cleanups subset E) Markus Armbruster
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=5721346B.4080000@redhat.com \
--to=eblake@redhat.com \
--cc=armbru@redhat.com \
--cc=mdroth@linux.vnet.ibm.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.