c687bc
From 46c3298774b976cc6a1cd834751e644fb482b08e Mon Sep 17 00:00:00 2001
c687bc
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
c687bc
Date: Wed, 16 Dec 2020 16:06:10 -0500
c687bc
Subject: [PATCH 09/14] error: New macro ERRP_GUARD()
c687bc
MIME-Version: 1.0
c687bc
Content-Type: text/plain; charset=UTF-8
c687bc
Content-Transfer-Encoding: 8bit
c687bc
c687bc
RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
c687bc
Message-id: <20201216160615.324213-6-marcandre.lureau@redhat.com>
c687bc
Patchwork-id: 100476
c687bc
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 05/10] error: New macro ERRP_GUARD()
c687bc
Bugzilla: 1859494
c687bc
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
c687bc
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
c687bc
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
c687bc
c687bc
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
c687bc
c687bc
Introduce a new ERRP_GUARD() macro, to be used at start of functions
c687bc
with an errp OUT parameter.
c687bc
c687bc
It has three goals:
c687bc
c687bc
1. Fix issue with error_fatal and error_prepend/error_append_hint: the
c687bc
user can't see this additional information, because exit() happens in
c687bc
error_setg earlier than information is added. [Reported by Greg Kurz]
c687bc
c687bc
2. Fix issue with error_abort and error_propagate: when we wrap
c687bc
error_abort by local_err+error_propagate, the resulting coredump will
c687bc
refer to error_propagate and not to the place where error happened.
c687bc
(the macro itself doesn't fix the issue, but it allows us to [3.] drop
c687bc
the local_err+error_propagate pattern, which will definitely fix the
c687bc
issue) [Reported by Kevin Wolf]
c687bc
c687bc
3. Drop local_err+error_propagate pattern, which is used to workaround
c687bc
void functions with errp parameter, when caller wants to know resulting
c687bc
status. (Note: actually these functions could be merely updated to
c687bc
return int error code).
c687bc
c687bc
To achieve these goals, later patches will add invocations
c687bc
of this macro at the start of functions with either use
c687bc
error_prepend/error_append_hint (solving 1) or which use
c687bc
local_err+error_propagate to check errors, switching those
c687bc
functions to use *errp instead (solving 2 and 3).
c687bc
c687bc
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
c687bc
Reviewed-by: Paul Durrant <paul@xen.org>
c687bc
Reviewed-by: Greg Kurz <groug@kaod.org>
c687bc
Reviewed-by: Eric Blake <eblake@redhat.com>
c687bc
[Merge comments properly with recent commit "error: Document Error API
c687bc
usage rules", and edit for clarity.  Put ERRP_AUTO_PROPAGATE() before
c687bc
its helpers, and touch up style.  Tweak commit message.]
c687bc
Signed-off-by: Markus Armbruster <armbru@redhat.com>
c687bc
Message-Id: <20200707165037.1026246-2-armbru@redhat.com>
c687bc
c687bc
(cherry picked from commit ae7c80a7bd73685437bf6ba9d7c26098351f4166)
c687bc
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
c687bc
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
c687bc
---
c687bc
 include/qapi/error.h | 158 +++++++++++++++++++++++++++++++++++++------
c687bc
 1 file changed, 139 insertions(+), 19 deletions(-)
c687bc
c687bc
diff --git a/include/qapi/error.h b/include/qapi/error.h
c687bc
index 08d48e74836..e658790acfc 100644
c687bc
--- a/include/qapi/error.h
c687bc
+++ b/include/qapi/error.h
c687bc
@@ -30,6 +30,10 @@
c687bc
  *   job.  Since the value of @errp is about handling the error, the
c687bc
  *   function should not examine it.
c687bc
  *
c687bc
+ * - The function may pass @errp to functions it calls to pass on
c687bc
+ *   their errors to its caller.  If it dereferences @errp to check
c687bc
+ *   for errors, it must use ERRP_GUARD().
c687bc
+ *
c687bc
  * - On success, the function should not touch *errp.  On failure, it
c687bc
  *   should set a new error, e.g. with error_setg(errp, ...), or
c687bc
  *   propagate an existing one, e.g. with error_propagate(errp, ...).
c687bc
@@ -45,15 +49,17 @@
c687bc
  * = Creating errors =
c687bc
  *
c687bc
  * Create an error:
c687bc
- *     error_setg(&err, "situation normal, all fouled up");
c687bc
+ *     error_setg(errp, "situation normal, all fouled up");
c687bc
+ * where @errp points to the location to receive the error.
c687bc
  *
c687bc
  * Create an error and add additional explanation:
c687bc
- *     error_setg(&err, "invalid quark");
c687bc
- *     error_append_hint(&err, "Valid quarks are up, down, strange, "
c687bc
+ *     error_setg(errp, "invalid quark");
c687bc
+ *     error_append_hint(errp, "Valid quarks are up, down, strange, "
c687bc
  *                       "charm, top, bottom.\n");
c687bc
+ * This may require use of ERRP_GUARD(); more on that below.
c687bc
  *
c687bc
  * Do *not* contract this to
c687bc
- *     error_setg(&err, "invalid quark\n" // WRONG!
c687bc
+ *     error_setg(errp, "invalid quark\n" // WRONG!
c687bc
  *                "Valid quarks are up, down, strange, charm, top, bottom.");
c687bc
  *
c687bc
  * = Reporting and destroying errors =
c687bc
@@ -107,18 +113,6 @@
c687bc
  * Errors get passed to the caller through the conventional @errp
c687bc
  * parameter.
c687bc
  *
c687bc
- * Pass an existing error to the caller:
c687bc
- *     error_propagate(errp, err);
c687bc
- * where Error **errp is a parameter, by convention the last one.
c687bc
- *
c687bc
- * Pass an existing error to the caller with the message modified:
c687bc
- *     error_propagate_prepend(errp, err,
c687bc
- *                             "Could not frobnicate '%s': ", name);
c687bc
- * This is more concise than
c687bc
- *     error_propagate(errp, err); // don't do this
c687bc
- *     error_prepend(errp, "Could not frobnicate '%s': ", name);
c687bc
- * and works even when @errp is &error_fatal.
c687bc
- *
c687bc
  * Create a new error and pass it to the caller:
c687bc
  *     error_setg(errp, "situation normal, all fouled up");
c687bc
  *
c687bc
@@ -129,18 +123,26 @@
c687bc
  *         handle the error...
c687bc
  *     }
c687bc
  * - when it does not, say because it is a void function:
c687bc
+ *     ERRP_GUARD();
c687bc
+ *     foo(arg, errp);
c687bc
+ *     if (*errp) {
c687bc
+ *         handle the error...
c687bc
+ *     }
c687bc
+ * More on ERRP_GUARD() below.
c687bc
+ *
c687bc
+ * Code predating ERRP_GUARD() still exists, and looks like this:
c687bc
  *     Error *err = NULL;
c687bc
  *     foo(arg, &err;;
c687bc
  *     if (err) {
c687bc
  *         handle the error...
c687bc
- *         error_propagate(errp, err);
c687bc
+ *         error_propagate(errp, err); // deprecated
c687bc
  *     }
c687bc
- * Do *not* "optimize" this to
c687bc
+ * Avoid in new code.  Do *not* "optimize" it to
c687bc
  *     foo(arg, errp);
c687bc
  *     if (*errp) { // WRONG!
c687bc
  *         handle the error...
c687bc
  *     }
c687bc
- * because errp may be NULL!
c687bc
+ * because errp may be NULL without the ERRP_GUARD() guard.
c687bc
  *
c687bc
  * But when all you do with the error is pass it on, please use
c687bc
  *     foo(arg, errp);
c687bc
@@ -160,6 +162,19 @@
c687bc
  *         handle the error...
c687bc
  *     }
c687bc
  *
c687bc
+ * Pass an existing error to the caller:
c687bc
+ *     error_propagate(errp, err);
c687bc
+ * This is rarely needed.  When @err is a local variable, use of
c687bc
+ * ERRP_GUARD() commonly results in more readable code.
c687bc
+ *
c687bc
+ * Pass an existing error to the caller with the message modified:
c687bc
+ *     error_propagate_prepend(errp, err,
c687bc
+ *                             "Could not frobnicate '%s': ", name);
c687bc
+ * This is more concise than
c687bc
+ *     error_propagate(errp, err); // don't do this
c687bc
+ *     error_prepend(errp, "Could not frobnicate '%s': ", name);
c687bc
+ * and works even when @errp is &error_fatal.
c687bc
+ *
c687bc
  * Receive and accumulate multiple errors (first one wins):
c687bc
  *     Error *err = NULL, *local_err = NULL;
c687bc
  *     foo(arg, &err;;
c687bc
@@ -187,6 +202,69 @@
c687bc
  *         error_setg(&err, ...); // WRONG!
c687bc
  *     }
c687bc
  * because this may pass a non-null err to error_setg().
c687bc
+ *
c687bc
+ * = Why, when and how to use ERRP_GUARD() =
c687bc
+ *
c687bc
+ * Without ERRP_GUARD(), use of the @errp parameter is restricted:
c687bc
+ * - It must not be dereferenced, because it may be null.
c687bc
+ * - It should not be passed to error_prepend() or
c687bc
+ *   error_append_hint(), because that doesn't work with &error_fatal.
c687bc
+ * ERRP_GUARD() lifts these restrictions.
c687bc
+ *
c687bc
+ * To use ERRP_GUARD(), add it right at the beginning of the function.
c687bc
+ * @errp can then be used without worrying about the argument being
c687bc
+ * NULL or &error_fatal.
c687bc
+ *
c687bc
+ * Using it when it's not needed is safe, but please avoid cluttering
c687bc
+ * the source with useless code.
c687bc
+ *
c687bc
+ * = Converting to ERRP_GUARD() =
c687bc
+ *
c687bc
+ * To convert a function to use ERRP_GUARD():
c687bc
+ *
c687bc
+ * 0. If the Error ** parameter is not named @errp, rename it to
c687bc
+ *    @errp.
c687bc
+ *
c687bc
+ * 1. Add an ERRP_GUARD() invocation, by convention right at the
c687bc
+ *    beginning of the function.  This makes @errp safe to use.
c687bc
+ *
c687bc
+ * 2. Replace &err by errp, and err by *errp.  Delete local variable
c687bc
+ *    @err.
c687bc
+ *
c687bc
+ * 3. Delete error_propagate(errp, *errp), replace
c687bc
+ *    error_propagate_prepend(errp, *errp, ...) by error_prepend(errp, ...)
c687bc
+ *
c687bc
+ * 4. Ensure @errp is valid at return: when you destroy *errp, set
c687bc
+ *    errp = NULL.
c687bc
+ *
c687bc
+ * Example:
c687bc
+ *
c687bc
+ *     bool fn(..., Error **errp)
c687bc
+ *     {
c687bc
+ *         Error *err = NULL;
c687bc
+ *
c687bc
+ *         foo(arg, &err;;
c687bc
+ *         if (err) {
c687bc
+ *             handle the error...
c687bc
+ *             error_propagate(errp, err);
c687bc
+ *             return false;
c687bc
+ *         }
c687bc
+ *         ...
c687bc
+ *     }
c687bc
+ *
c687bc
+ * becomes
c687bc
+ *
c687bc
+ *     bool fn(..., Error **errp)
c687bc
+ *     {
c687bc
+ *         ERRP_GUARD();
c687bc
+ *
c687bc
+ *         foo(arg, errp);
c687bc
+ *         if (*errp) {
c687bc
+ *             handle the error...
c687bc
+ *             return false;
c687bc
+ *         }
c687bc
+ *         ...
c687bc
+ *     }
c687bc
  */
c687bc
 
c687bc
 #ifndef ERROR_H
c687bc
@@ -287,6 +365,7 @@ void error_setg_win32_internal(Error **errp,
c687bc
  * the error object.
c687bc
  * Else, move the error object from @local_err to *@dst_errp.
c687bc
  * On return, @local_err is invalid.
c687bc
+ * Please use ERRP_GUARD() instead when possible.
c687bc
  * Please don't error_propagate(&error_fatal, ...), use
c687bc
  * error_report_err() and exit(), because that's more obvious.
c687bc
  */
c687bc
@@ -298,6 +377,7 @@ void error_propagate(Error **dst_errp, Error *local_err);
c687bc
  * Behaves like
c687bc
  *     error_prepend(&local_err, fmt, ...);
c687bc
  *     error_propagate(dst_errp, local_err);
c687bc
+ * Please use ERRP_GUARD() and error_prepend() instead when possible.
c687bc
  */
c687bc
 void error_propagate_prepend(Error **dst_errp, Error *local_err,
c687bc
                              const char *fmt, ...);
c687bc
@@ -395,6 +475,46 @@ void error_set_internal(Error **errp,
c687bc
                         ErrorClass err_class, const char *fmt, ...)
c687bc
     GCC_FMT_ATTR(6, 7);
c687bc
 
c687bc
+/*
c687bc
+ * Make @errp parameter easier to use regardless of argument value
c687bc
+ *
c687bc
+ * This macro is for use right at the beginning of a function that
c687bc
+ * takes an Error **errp parameter to pass errors to its caller.  The
c687bc
+ * parameter must be named @errp.
c687bc
+ *
c687bc
+ * It must be used when the function dereferences @errp or passes
c687bc
+ * @errp to error_prepend(), error_vprepend(), or error_append_hint().
c687bc
+ * It is safe to use even when it's not needed, but please avoid
c687bc
+ * cluttering the source with useless code.
c687bc
+ *
c687bc
+ * If @errp is NULL or &error_fatal, rewrite it to point to a local
c687bc
+ * Error variable, which will be automatically propagated to the
c687bc
+ * original @errp on function exit.
c687bc
+ *
c687bc
+ * Note: &error_abort is not rewritten, because that would move the
c687bc
+ * abort from the place where the error is created to the place where
c687bc
+ * it's propagated.
c687bc
+ */
c687bc
+#define ERRP_GUARD()                                            \
c687bc
+    g_auto(ErrorPropagator) _auto_errp_prop = {.errp = errp};   \
c687bc
+    do {                                                        \
c687bc
+        if (!errp || errp == &error_fatal) {                    \
c687bc
+            errp = &_auto_errp_prop.local_err;                  \
c687bc
+        }                                                       \
c687bc
+    } while (0)
c687bc
+
c687bc
+typedef struct ErrorPropagator {
c687bc
+    Error *local_err;
c687bc
+    Error **errp;
c687bc
+} ErrorPropagator;
c687bc
+
c687bc
+static inline void error_propagator_cleanup(ErrorPropagator *prop)
c687bc
+{
c687bc
+    error_propagate(prop->errp, prop->local_err);
c687bc
+}
c687bc
+
c687bc
+G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup);
c687bc
+
c687bc
 /*
c687bc
  * Special error destination to abort on error.
c687bc
  * See error_setg() and error_propagate() for details.
c687bc
-- 
c687bc
2.27.0
c687bc