From: Markus Armbruster <armbru@redhat.com>
To: Eric Blake <eblake@redhat.com>
Cc: qemu-devel@nongnu.org, Michael Roth <mdroth@linux.vnet.ibm.com>
Subject: Re: [Qemu-devel] [PATCH for-2.5] error: Document chained error handling
Date: Tue, 17 Nov 2015 14:48:25 +0100 [thread overview]
Message-ID: <87egfospna.fsf@blackfin.pond.sub.org> (raw)
In-Reply-To: <1447352454-29349-1-git-send-email-eblake@redhat.com> (Eric Blake's message of "Thu, 12 Nov 2015 11:20:54 -0700")
Eric Blake <eblake@redhat.com> writes:
> The current output of the qapi code generator includes some chained
> error handling, which looks like:
>
> | visit_start_struct(v, (void **)obj, "foo", name, sizeof(FOO), &err);
> | if (!err) {
> | if (*obj) {
> | visit_type_FOO_fields(v, obj, errp);
> | }
> | visit_end_struct(v, &err);
> | }
> | error_propagate(errp, err);
>
> Although there are plans to revisit that code for qemu 2.6, it is
> still a useful idiom to mention. It is safe because error_propagate()
> is different than most functions in that you can pass in an
> already-set errp, and it still does the right thing.
>
> Also, describe an alternative form of chained error handling that was
> proposed during the qapi work, and which may be a bit more obvious
> to a reader what is happening:
>
> | visit_start_implicit_struct(v, (void **)obj, sizeof(FOO), &err);
> | if (!err) {
> | visit_type_FOO_fields(v, obj, &err);
> | visit_end_implicit_struct(v, err ? NULL : &err);
> | }
> | error_propagate(errp, err);
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
>
> ---
> based on feedback of my qapi series v5 7/46; doc only, so might
> be worth having in 2.5
> ---
> include/qapi/error.h | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index 4d42cdc..4310195 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -76,6 +76,21 @@
> * But when all you do with the error is pass it on, please use
> * foo(arg, errp);
> * for readability.
> + *
> + * In a situation where cleanup must happen even if a first step fails,
> + * but the cleanup may also set an error, the first error to occur will
> + * take priority when combined by:
> + * Error *err = NULL;
> + * action1(arg, errp);
> + * action2(arg, &err);
> + * error_propagate(errp, err);
> + * or by:
> + * Error *err = NULL;
> + * action1(arg, &err);
> + * action2(arg, err ? NULL : &err);
> + * error_propagate(errp, err);
> + * although the second form is required if any further error handling
> + * will inspect err to see if all earlier locations succeeded.
> */
>
> #ifndef ERROR_H
Yet another one:
* Error *err = NULL, *local_err = NULL;
* action1(arg, &err);
* action2(arg, &local_err)
* error_propagate(&err, err);
* error_propagate(errp, err);
Less clever.
Can we find a single, recommended way to do this? See below.
Not mentioned: the obvious
action1(arg, errp);
action2(arg, errp);
is wrong, because a non-null Error ** argument must point to a null. It
isn't when errp is non-null, and action1() sets an error. It actually
fails an assertion in error_setv() when action2() sets an error other
than with error_propagate().
The existing how-to comment doesn't spell this out. It always shows the
required err = NULL, though. You can derive "must point to null" from
the function comments of error_setg() and error_propagate().
I agree the how-to comment could use a section on accumulating errors.
Your patch adds one on "accumulate and pass to caller". Here's my
attempt:
diff --git a/include/qapi/error.h b/include/qapi/error.h
index 4d42cdc..b2362a5 100644
--- a/include/qapi/error.h
+++ b/include/qapi/error.h
@@ -76,6 +76,23 @@
* But when all you do with the error is pass it on, please use
* foo(arg, errp);
* for readability.
+ *
+ * Receive and accumulate multiple errors (first one wins):
+ * Error *err = NULL, *local_err = NULL;
+ * foo(arg, &err);
+ * bar(arg, &local_err);
+ * error_propagate(&err, local_err);
+ * if (err) {
+ * handle the error...
+ * }
+ *
+ * Do *not* "optimize" this to
+ * foo(arg, &err);
+ * bar(arg, &err); // WRONG!
+ * if (err) {
+ * handle the error...
+ * }
+ * because this may pass a non-null err to bar().
*/
#ifndef ERROR_H
Leaves replacing &err by errp when the value of err isn't needed to the
reader. I think that's okay given we've shown it already above.
What do you think?
next prev parent reply other threads:[~2015-11-17 13:48 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-12 18:20 [Qemu-devel] [PATCH for-2.5] error: Document chained error handling Eric Blake
2015-11-17 13:48 ` Markus Armbruster [this message]
2015-11-17 15:11 ` Eric Blake
2015-11-17 15:36 ` 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=87egfospna.fsf@blackfin.pond.sub.org \
--to=armbru@redhat.com \
--cc=eblake@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.